/** @file | |
Helper functions for configuring or obtaining the parameters relating to IP6. | |
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR> | |
This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php. | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
#include "Ip6Impl.h" | |
CHAR16 mIp6ConfigStorageName[] = L"IP6_CONFIG_IFR_NVDATA"; | |
/** | |
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 | |
Ip6ConfigManualAddressNotify ( | |
IN EFI_EVENT Event, | |
IN VOID *Context | |
) | |
{ | |
*((BOOLEAN *) Context) = TRUE; | |
} | |
/** | |
Get the configuration data for the EFI IPv6 network stack running on the | |
communication. It is a help function to the call EfiIp6ConfigGetData(). | |
@param[in] Ip6Config The pointer to the EFI_IP6_CONFIG_PROTOCOL instance. | |
@param[in] DataType The type of data to get. | |
@param[out] DataSize The size of buffer required in bytes. | |
@param[out] Data The data buffer in which the configuration data is returned. The | |
type of the data buffer associated with the DataType. | |
It is the caller's responsibility to free the resource. | |
@retval EFI_SUCCESS The specified configuration data was obtained successfully. | |
@retval EFI_INVALID_PARAMETER One or more of the followings are TRUE: | |
- Ip6Config is NULL or invalid. | |
- DataSize is NULL. | |
- Data is NULL. | |
@retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resources. | |
@retval EFI_NOT_READY The specified configuration data is not ready due to an | |
asynchronous configuration process already in progress. | |
@retval EFI_NOT_FOUND The specified configuration data was not found. | |
**/ | |
EFI_STATUS | |
Ip6ConfigNvGetData ( | |
IN EFI_IP6_CONFIG_PROTOCOL *Ip6Config, | |
IN EFI_IP6_CONFIG_DATA_TYPE DataType, | |
OUT UINTN *DataSize, | |
OUT VOID **Data | |
) | |
{ | |
UINTN BufferSize; | |
VOID *Buffer; | |
EFI_STATUS Status; | |
if ((Ip6Config == NULL) || (Data == NULL) || (DataSize == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
BufferSize = 0; | |
Status = Ip6Config->GetData ( | |
Ip6Config, | |
DataType, | |
&BufferSize, | |
NULL | |
); | |
if (Status != EFI_BUFFER_TOO_SMALL) { | |
return Status; | |
} | |
Buffer = AllocateZeroPool (BufferSize); | |
if (Buffer == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Status = Ip6Config->GetData ( | |
Ip6Config, | |
DataType, | |
&BufferSize, | |
Buffer | |
); | |
if (EFI_ERROR (Status)) { | |
FreePool (Buffer); | |
return Status; | |
} | |
*DataSize = BufferSize; | |
*Data = Buffer; | |
return EFI_SUCCESS; | |
} | |
/** | |
Free all nodes in IP6_ADDRESS_INFO_ENTRY in the list array specified | |
with ListHead. | |
@param[in] ListHead The head of the list array in IP6_ADDRESS_INFO_ENTRY. | |
**/ | |
VOID | |
Ip6FreeAddressInfoList ( | |
IN LIST_ENTRY *ListHead | |
) | |
{ | |
IP6_ADDRESS_INFO_ENTRY *Node; | |
LIST_ENTRY *Entry; | |
LIST_ENTRY *NextEntry; | |
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, ListHead) { | |
Node = NET_LIST_USER_STRUCT (Entry, IP6_ADDRESS_INFO_ENTRY, Link); | |
RemoveEntryList (&Node->Link); | |
FreePool (Node); | |
} | |
} | |
/** | |
Convert the IPv6 address into a formatted string. | |
@param[in] Ip6 The IPv6 address. | |
@param[out] Str The formatted IP string. | |
**/ | |
VOID | |
Ip6ToStr ( | |
IN EFI_IPv6_ADDRESS *Ip6, | |
OUT CHAR16 *Str | |
) | |
{ | |
UINTN Index; | |
BOOLEAN Short; | |
UINTN Number; | |
CHAR16 FormatString[8]; | |
Short = FALSE; | |
for (Index = 0; Index < 15; Index = Index + 2) { | |
if (!Short && | |
Index % 2 == 0 && | |
Ip6->Addr[Index] == 0 && | |
Ip6->Addr[Index + 1] == 0 | |
) { | |
// | |
// Deal with the case of ::. | |
// | |
if (Index == 0) { | |
*Str = L':'; | |
*(Str + 1) = L':'; | |
Str = Str + 2; | |
} else { | |
*Str = L':'; | |
Str = Str + 1; | |
} | |
while ((Index < 15) && (Ip6->Addr[Index] == 0) && (Ip6->Addr[Index + 1] == 0)) { | |
Index = Index + 2; | |
} | |
Short = TRUE; | |
if (Index == 16) { | |
// | |
// :: is at the end of the address. | |
// | |
*Str = L'\0'; | |
break; | |
} | |
} | |
ASSERT (Index < 15); | |
if (Ip6->Addr[Index] == 0) { | |
Number = UnicodeSPrint (Str, 2 * IP6_STR_MAX_SIZE, L"%x:", (UINTN) Ip6->Addr[Index + 1]); | |
} else { | |
if (Ip6->Addr[Index + 1] < 0x10) { | |
CopyMem (FormatString, L"%x0%x:", StrSize (L"%x0%x:")); | |
} else { | |
CopyMem (FormatString, L"%x%x:", StrSize (L"%x%x:")); | |
} | |
Number = UnicodeSPrint ( | |
Str, | |
2 * IP6_STR_MAX_SIZE, | |
(CONST CHAR16 *) FormatString, | |
(UINTN) Ip6->Addr[Index], | |
(UINTN) Ip6->Addr[Index + 1] | |
); | |
} | |
Str = Str + Number; | |
if (Index + 2 == 16) { | |
*Str = L'\0'; | |
if (*(Str - 1) == L':') { | |
*(Str - 1) = L'\0'; | |
} | |
} | |
} | |
} | |
/** | |
Convert EFI_IP6_CONFIG_INTERFACE_ID to string format. | |
@param[out] String The buffer to store the converted string. | |
@param[in] IfId The pointer of EFI_IP6_CONFIG_INTERFACE_ID. | |
@retval EFI_SUCCESS The string converted successfully. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
**/ | |
EFI_STATUS | |
Ip6ConvertInterfaceIdToString ( | |
OUT CHAR16 *String, | |
IN EFI_IP6_CONFIG_INTERFACE_ID *IfId | |
) | |
{ | |
UINT8 Index; | |
UINTN Number; | |
if ((String == NULL) || (IfId == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
for (Index = 0; Index < 8; Index++) { | |
Number = UnicodeSPrint ( | |
String, | |
2 * INTERFACE_ID_STR_STORAGE, | |
L"%x:", | |
(UINTN) IfId->Id[Index] | |
); | |
String = String + Number; | |
} | |
*(String - 1) = '\0'; | |
return EFI_SUCCESS; | |
} | |
/** | |
Parse InterfaceId in string format and convert it to EFI_IP6_CONFIG_INTERFACE_ID. | |
@param[in] String The buffer of the string to be parsed. | |
@param[out] IfId The pointer of EFI_IP6_CONFIG_INTERFACE_ID. | |
@retval EFI_SUCCESS The operation finished successfully. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
**/ | |
EFI_STATUS | |
Ip6ParseInterfaceIdFromString ( | |
IN CONST CHAR16 *String, | |
OUT EFI_IP6_CONFIG_INTERFACE_ID *IfId | |
) | |
{ | |
UINT8 Index; | |
CHAR16 *IfIdStr; | |
CHAR16 *TempStr; | |
UINTN NodeVal; | |
if ((String == NULL) || (IfId == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
IfIdStr = (CHAR16 *) String; | |
ZeroMem (IfId, sizeof (EFI_IP6_CONFIG_INTERFACE_ID)); | |
for (Index = 0; Index < 8; Index++) { | |
TempStr = IfIdStr; | |
while ((*IfIdStr != L'\0') && (*IfIdStr != L':')) { | |
IfIdStr++; | |
} | |
// | |
// The InterfaceId format is X:X:X:X, the number of X should not exceed 8. | |
// If the number of X is less than 8, zero is appended to the InterfaceId. | |
// | |
if ((*IfIdStr == ':') && (Index == 7)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// Convert the string to interface id. AsciiStrHexToUintn stops at the | |
// first character that is not a valid hex character, ':' or '\0' here. | |
// | |
NodeVal = StrHexToUintn (TempStr); | |
if (NodeVal > 0xFF) { | |
return EFI_INVALID_PARAMETER; | |
} | |
IfId->Id[Index] = (UINT8) NodeVal; | |
IfIdStr++; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Create Hii Extend Label OpCode as the start opcode and end opcode. It is | |
a help function. | |
@param[in] StartLabelNumber The number of start label. | |
@param[out] StartOpCodeHandle Points to the start opcode handle. | |
@param[out] StartLabel Points to the created start opcode. | |
@param[out] EndOpCodeHandle Points to the end opcode handle. | |
@param[out] EndLabel Points to the created end opcode. | |
@retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this | |
operation. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
@retval EFI_SUCCESS The operation completed successfully. | |
**/ | |
EFI_STATUS | |
Ip6CreateOpCode ( | |
IN UINT16 StartLabelNumber, | |
OUT VOID **StartOpCodeHandle, | |
OUT EFI_IFR_GUID_LABEL **StartLabel, | |
OUT VOID **EndOpCodeHandle, | |
OUT EFI_IFR_GUID_LABEL **EndLabel | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_IFR_GUID_LABEL *InternalStartLabel; | |
EFI_IFR_GUID_LABEL *InternalEndLabel; | |
if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
*StartOpCodeHandle = NULL; | |
*EndOpCodeHandle = NULL; | |
Status = EFI_OUT_OF_RESOURCES; | |
// | |
// Initialize the container for dynamic opcodes. | |
// | |
*StartOpCodeHandle = HiiAllocateOpCodeHandle (); | |
if (*StartOpCodeHandle == NULL) { | |
return Status; | |
} | |
*EndOpCodeHandle = HiiAllocateOpCodeHandle (); | |
if (*EndOpCodeHandle == NULL) { | |
goto Exit; | |
} | |
// | |
// Create Hii Extend Label OpCode as the start opcode. | |
// | |
InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( | |
*StartOpCodeHandle, | |
&gEfiIfrTianoGuid, | |
NULL, | |
sizeof (EFI_IFR_GUID_LABEL) | |
); | |
if (InternalStartLabel == NULL) { | |
goto Exit; | |
} | |
InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; | |
InternalStartLabel->Number = StartLabelNumber; | |
// | |
// Create Hii Extend Label OpCode as the end opcode. | |
// | |
InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( | |
*EndOpCodeHandle, | |
&gEfiIfrTianoGuid, | |
NULL, | |
sizeof (EFI_IFR_GUID_LABEL) | |
); | |
if (InternalEndLabel == NULL) { | |
goto Exit; | |
} | |
InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; | |
InternalEndLabel->Number = LABEL_END; | |
*StartLabel = InternalStartLabel; | |
*EndLabel = InternalEndLabel; | |
return EFI_SUCCESS; | |
Exit: | |
if (*StartOpCodeHandle != NULL) { | |
HiiFreeOpCodeHandle (*StartOpCodeHandle); | |
} | |
if (*EndOpCodeHandle != NULL) { | |
HiiFreeOpCodeHandle (*EndOpCodeHandle); | |
} | |
return Status; | |
} | |
/** | |
This function converts the different format of address list to string format and | |
then generates the corresponding text opcode to illustarate the address info in | |
IP6 configuration page. Currently, the following formats are supported: | |
EFI_IP6_ADDRESS_INFO AddressType: Ip6ConfigNvHostAddress; | |
EFI_IPv6_ADDRESS AddressType: Ip6ConfigNvGatewayAddress and Ip6ConfigNvDnsAddress; | |
EFI_IP6_ROUTE_TABLE AddressType: Ip6ConfigNvRouteTable. | |
@param[in, out] String The pointer to the buffer to store the converted | |
string. | |
@param[in] HiiHandle A handle that was previously registered in the | |
HII Database. | |
@param[in] AddressType The address type. | |
@param[in] AddressInfo Pointer to the address list. | |
@param[in] AddressCount The address count of the address list. | |
@retval EFI_SUCCESS The operation finished successfully. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
@retval EFI_UNSUPPORTED The AddressType is not supported. | |
**/ | |
EFI_STATUS | |
Ip6ConvertAddressListToString ( | |
IN OUT CHAR16 *String, | |
IN EFI_HII_HANDLE HiiHandle, | |
IN IP6_CONFIG_NV_ADDRESS_TYPE AddressType, | |
IN VOID *AddressInfo, | |
IN UINTN AddressCount | |
) | |
{ | |
UINTN Index; | |
UINTN Number; | |
CHAR16 *TempStr; | |
EFI_STATUS Status; | |
VOID *StartOpCodeHandle; | |
EFI_IFR_GUID_LABEL *StartLabel; | |
VOID *EndOpCodeHandle; | |
EFI_IFR_GUID_LABEL *EndLabel; | |
UINT16 StartLabelNumber; | |
EFI_STRING_ID TextTwo; | |
UINT8 *AddressHead; | |
UINT8 PrefixLength; | |
EFI_IPv6_ADDRESS *Address; | |
if ((String == NULL) || (HiiHandle == NULL) || (AddressInfo == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (AddressType == Ip6ConfigNvHostAddress) { | |
StartLabelNumber = HOST_ADDRESS_LABEL; | |
} else if (AddressType == Ip6ConfigNvGatewayAddress) { | |
StartLabelNumber = GATEWAY_ADDRESS_LABEL; | |
} else if (AddressType == Ip6ConfigNvDnsAddress) { | |
StartLabelNumber = DNS_ADDRESS_LABEL; | |
} else if (AddressType == Ip6ConfigNvRouteTable) { | |
StartLabelNumber = ROUTE_TABLE_LABEL; | |
} else { | |
ASSERT (FALSE); | |
return EFI_UNSUPPORTED; | |
} | |
Status = Ip6CreateOpCode ( | |
StartLabelNumber, | |
&StartOpCodeHandle, | |
&StartLabel, | |
&EndOpCodeHandle, | |
&EndLabel | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
AddressHead = (UINT8 *) AddressInfo; | |
for (Index = 0; Index < AddressCount; Index++) { | |
if (AddressType == Ip6ConfigNvHostAddress) { | |
AddressInfo = AddressHead + sizeof (EFI_IP6_ADDRESS_INFO) * Index; | |
Address = &((EFI_IP6_ADDRESS_INFO *) AddressInfo)->Address; | |
} else if (AddressType == Ip6ConfigNvRouteTable) { | |
AddressInfo = AddressHead + sizeof (EFI_IP6_ROUTE_TABLE) * Index; | |
Address = &((EFI_IP6_ROUTE_TABLE *) AddressInfo)->Destination; | |
} else { | |
AddressInfo = AddressHead + sizeof (EFI_IPv6_ADDRESS) * Index; | |
Address = AddressInfo; | |
} | |
// | |
// Convert the IP address info to string. | |
// | |
Ip6ToStr (Address, String); | |
TempStr = String + StrLen (String); | |
if ((AddressType == Ip6ConfigNvHostAddress) || (AddressType == Ip6ConfigNvRouteTable)) { | |
if (AddressType == Ip6ConfigNvHostAddress) { | |
PrefixLength = ((EFI_IP6_ADDRESS_INFO *) AddressInfo)->PrefixLength; | |
} else { | |
PrefixLength = ((EFI_IP6_ROUTE_TABLE *) AddressInfo)->PrefixLength; | |
} | |
// | |
// Append the prefix length to the string. | |
// | |
*TempStr = L'/'; | |
TempStr++; | |
Number = UnicodeSPrint (TempStr, 6, L"%d", PrefixLength); | |
TempStr = TempStr + Number; | |
} | |
if (AddressType == Ip6ConfigNvRouteTable) { | |
// | |
// Append " >> " to the string. | |
// | |
Number = UnicodeSPrint (TempStr, 8, L" >> "); | |
TempStr = TempStr + Number; | |
// | |
// Append the gateway address to the string. | |
// | |
Ip6ToStr (&((EFI_IP6_ROUTE_TABLE *) AddressInfo)->Gateway, TempStr); | |
TempStr = TempStr + StrLen (TempStr); | |
} | |
// | |
// Generate a text opcode and update the UI. | |
// | |
TextTwo = HiiSetString (HiiHandle, 0, String, NULL); | |
if (TextTwo == 0) { | |
Status = EFI_INVALID_PARAMETER; | |
goto Exit; | |
} | |
HiiCreateTextOpCode (StartOpCodeHandle, STR_NULL, STR_NULL, TextTwo); | |
String = TempStr; | |
*String = IP6_ADDRESS_DELIMITER; | |
String++; | |
} | |
*(String - 1) = '\0'; | |
Status = HiiUpdateForm ( | |
HiiHandle, // HII handle | |
&gIp6ConfigNvDataGuid, // Formset GUID | |
FORMID_MAIN_FORM, // Form ID | |
StartOpCodeHandle, // Label for where to insert opcodes | |
EndOpCodeHandle // Replace data | |
); | |
Exit: | |
HiiFreeOpCodeHandle (StartOpCodeHandle); | |
HiiFreeOpCodeHandle (EndOpCodeHandle); | |
return Status; | |
} | |
/** | |
Parse address list in string format and convert it to a list array of node in | |
IP6_ADDRESS_INFO_ENTRY. | |
@param[in] String The buffer to string to be parsed. | |
@param[out] ListHead The list head of array. | |
@param[out] AddressCount The number of list nodes in the array. | |
@retval EFI_SUCCESS The operation finished successfully. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
@retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of resource. | |
**/ | |
EFI_STATUS | |
Ip6ParseAddressListFromString ( | |
IN CONST CHAR16 *String, | |
OUT LIST_ENTRY *ListHead, | |
OUT UINT32 *AddressCount | |
) | |
{ | |
EFI_STATUS Status; | |
CHAR16 *LocalString; | |
CHAR16 *Temp; | |
CHAR16 *TempStr; | |
EFI_IP6_ADDRESS_INFO AddressInfo; | |
IP6_ADDRESS_INFO_ENTRY *Node; | |
BOOLEAN Last; | |
UINT32 Count; | |
if ((String == NULL) || (ListHead == NULL) || (AddressCount == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
ZeroMem (&AddressInfo, sizeof (EFI_IP6_ADDRESS_INFO)); | |
LocalString = (CHAR16 *) AllocateCopyPool (StrSize (String), String); | |
if (LocalString == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
// | |
// Clean the original address list. | |
// | |
Ip6FreeAddressInfoList (ListHead); | |
Temp = LocalString; | |
Last = FALSE; | |
Count = 0; | |
while (*LocalString != L'\0') { | |
TempStr = LocalString; | |
while ((*LocalString != L'\0') && (*LocalString != IP6_ADDRESS_DELIMITER)) { | |
LocalString++; | |
} | |
if (*LocalString == L'\0') { | |
Last = TRUE; | |
} | |
*LocalString = L'\0'; | |
Status = NetLibStrToIp6andPrefix (TempStr, &AddressInfo.Address, &AddressInfo.PrefixLength); | |
if (EFI_ERROR (Status)) { | |
goto Error; | |
} | |
if (AddressInfo.PrefixLength == 0xFF) { | |
AddressInfo.PrefixLength = 0; | |
} | |
if (!NetIp6IsValidUnicast (&AddressInfo.Address)) { | |
Status = EFI_INVALID_PARAMETER; | |
goto Error; | |
} | |
Node = AllocatePool (sizeof (IP6_ADDRESS_INFO_ENTRY)); | |
if (Node == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Error; | |
} | |
CopyMem (&Node->AddrInfo, &AddressInfo, sizeof (EFI_IP6_ADDRESS_INFO)); | |
InsertTailList (ListHead, &Node->Link); | |
Count++; | |
if (Last) { | |
break; | |
} | |
LocalString++; | |
} | |
FreePool (Temp); | |
*AddressCount = Count; | |
return EFI_SUCCESS; | |
Error: | |
Ip6FreeAddressInfoList (ListHead); | |
FreePool (Temp); | |
return Status; | |
} | |
/** | |
This function converts the interface info to string and draws it to the IP6 UI. | |
The interface information includes interface name, interface type, hardware | |
address and route table information. | |
@param[in] IfInfo The pointer of EFI_IP6_CONFIG_INTERFACE_INFO. | |
@param[in] HiiHandle The handle that was previously registered in the | |
HII Database. | |
@param[in, out] IfrNvData Points to IP6_CONFIG_IFR_NVDATA. | |
@retval EFI_SUCCESS The operation finished successfully. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
@retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources. | |
**/ | |
EFI_STATUS | |
Ip6ConvertInterfaceInfoToString ( | |
IN EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo, | |
IN EFI_HII_HANDLE HiiHandle, | |
IN OUT IP6_CONFIG_IFR_NVDATA *IfrNvData | |
) | |
{ | |
UINT32 Index; | |
UINTN Number; | |
CHAR16 *String; | |
CHAR16 PortString[ADDRESS_STR_MAX_SIZE]; | |
CHAR16 FormatString[8]; | |
EFI_STRING_ID StringId; | |
if ((IfInfo == NULL) || (HiiHandle == NULL) || (IfrNvData == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// Print the interface name. | |
// | |
StringId = HiiSetString ( | |
HiiHandle, | |
STRING_TOKEN (STR_IP6_INTERFACE_NAME_CONTENT), | |
IfInfo->Name, | |
NULL | |
); | |
if (StringId == 0) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
// | |
// Print the interface type. | |
// | |
if (IfInfo->IfType == Ip6InterfaceTypeEthernet) { | |
CopyMem (PortString, IP6_ETHERNET, sizeof (IP6_ETHERNET)); | |
} else if (IfInfo->IfType == Ip6InterfaceTypeExperimentalEthernet) { | |
CopyMem (PortString, IP6_EXPERIMENTAL_ETHERNET, sizeof (IP6_EXPERIMENTAL_ETHERNET)); | |
} else { | |
// | |
// Refer to RFC1700, chapter Number Hardware Type. | |
// | |
UnicodeSPrint (PortString, 6, L"%d", IfInfo->IfType); | |
} | |
StringId = HiiSetString ( | |
HiiHandle, | |
STRING_TOKEN (STR_IP6_INTERFACE_TYPE_CONTENT), | |
PortString, | |
NULL | |
); | |
if (StringId == 0) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
// | |
// Convert the hardware address. | |
// | |
String = PortString; | |
ASSERT (IfInfo->HwAddressSize <= 32); | |
for (Index = 0; Index < IfInfo->HwAddressSize; Index++) { | |
if (IfInfo->HwAddress.Addr[Index] < 0x10) { | |
CopyMem (FormatString, L"0%x-", sizeof (L"0%x-")); | |
} else { | |
CopyMem (FormatString, L"%x-", sizeof (L"%x-")); | |
} | |
Number = UnicodeSPrint ( | |
String, | |
8, | |
(CONST CHAR16 *) FormatString, | |
(UINTN) IfInfo->HwAddress.Addr[Index] | |
); | |
String = String + Number; | |
} | |
if (Index != 0) { | |
ASSERT (String > PortString); | |
String--; | |
*String = '\0'; | |
} | |
// | |
// Print the hardware address. | |
// | |
StringId = HiiSetString ( | |
HiiHandle, | |
STRING_TOKEN (STR_IP6_MAC_ADDRESS_CONTENT), | |
PortString, | |
NULL | |
); | |
if (StringId == 0) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Build the address info list from list array of node in IP6_ADDRESS_INFO_ENTRY. | |
@param[in] Instance Points to IP6 config instance data. | |
@param[in] AddressType The address type. | |
@param[out] AddressInfo The pointer to the buffer to store the address list. | |
@param[out] AddressSize The address size of the address list. | |
@retval EFI_SUCCESS The operation finished successfully. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
@retval EFI_UNSUPPORTED The AddressType is not supported. | |
**/ | |
EFI_STATUS | |
Ip6BuildNvAddressInfo ( | |
IN IP6_CONFIG_INSTANCE *Instance, | |
IN IP6_CONFIG_NV_ADDRESS_TYPE AddressType, | |
OUT VOID **AddressInfo, | |
OUT UINTN *AddressSize | |
) | |
{ | |
IP6_CONFIG_NVDATA *Ip6NvData; | |
LIST_ENTRY *Entry; | |
LIST_ENTRY *ListHead; | |
IP6_ADDRESS_INFO_ENTRY *Node; | |
VOID *AddressList; | |
VOID *TmpStr; | |
UINTN DataSize; | |
EFI_IPv6_ADDRESS *Ip6Address; | |
EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress; | |
if ((Instance == NULL) || (AddressInfo == NULL) || (AddressSize == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE); | |
Ip6NvData = &Instance->Ip6NvData; | |
if (AddressType == Ip6ConfigNvHostAddress) { | |
ListHead = &Ip6NvData->ManualAddress; | |
DataSize = sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS) * Ip6NvData->ManualAddressCount; | |
} else if (AddressType == Ip6ConfigNvGatewayAddress) { | |
ListHead = &Ip6NvData->GatewayAddress; | |
DataSize = sizeof (EFI_IPv6_ADDRESS) * Ip6NvData->GatewayAddressCount; | |
} else if (AddressType == Ip6ConfigNvDnsAddress) { | |
ListHead = &Ip6NvData->DnsAddress; | |
DataSize = sizeof (EFI_IPv6_ADDRESS) * Ip6NvData->DnsAddressCount; | |
} else { | |
return EFI_UNSUPPORTED; | |
} | |
AddressList = AllocateZeroPool (DataSize); | |
if (AddressList == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
TmpStr = AddressList; | |
NET_LIST_FOR_EACH (Entry, ListHead) { | |
Node = NET_LIST_USER_STRUCT (Entry, IP6_ADDRESS_INFO_ENTRY, Link); | |
if (AddressType == Ip6ConfigNvHostAddress) { | |
ManualAddress = (EFI_IP6_CONFIG_MANUAL_ADDRESS *) AddressList; | |
IP6_COPY_ADDRESS (&ManualAddress->Address, &Node->AddrInfo.Address); | |
ManualAddress->PrefixLength = Node->AddrInfo.PrefixLength; | |
AddressList = (UINT8 *) AddressList + sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS); | |
} else { | |
Ip6Address = (EFI_IPv6_ADDRESS *) AddressList; | |
IP6_COPY_ADDRESS (Ip6Address, &Node->AddrInfo.Address); | |
AddressList = (UINT8 *) AddressList + sizeof (EFI_IPv6_ADDRESS); | |
} | |
} | |
*AddressInfo = TmpStr; | |
*AddressSize = DataSize; | |
return EFI_SUCCESS; | |
} | |
/** | |
Convert the IP6 configuration data into the IFR data. | |
@param[in, out] IfrNvData The IFR NV data. | |
@param[in] Instance The IP6 config instance data. | |
@retval EFI_SUCCESS The operation finished successfully. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
@retval EFI_UNSUPPORTED The policy is not supported in the current implementation. | |
@retval Others Other errors as indicated. | |
**/ | |
EFI_STATUS | |
Ip6ConvertConfigNvDataToIfrNvData ( | |
IN OUT IP6_CONFIG_IFR_NVDATA *IfrNvData, | |
IN IP6_CONFIG_INSTANCE *Instance | |
) | |
{ | |
IP6_CONFIG_NVDATA *Ip6NvData; | |
EFI_IP6_CONFIG_PROTOCOL *Ip6Config; | |
UINTN DataSize; | |
VOID *Data; | |
EFI_STATUS Status; | |
EFI_IP6_CONFIG_POLICY Policy; | |
EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits; | |
EFI_HII_HANDLE HiiHandle; | |
if ((IfrNvData == NULL) || (Instance == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE); | |
Ip6Config = &Instance->Ip6Config; | |
Ip6NvData = &Instance->Ip6NvData; | |
Data = NULL; | |
DataSize = 0; | |
HiiHandle = Instance->CallbackInfo.RegisteredHandle; | |
// | |
// Get the current interface info. | |
// | |
Status = Ip6ConfigNvGetData ( | |
Ip6Config, | |
Ip6ConfigDataTypeInterfaceInfo, | |
&DataSize, | |
(VOID **) &Data | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
// | |
// Convert the interface info to string and print. | |
// | |
Status = Ip6ConvertInterfaceInfoToString ( | |
(EFI_IP6_CONFIG_INTERFACE_INFO *) Data, | |
HiiHandle, | |
IfrNvData | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
// | |
// Get the interface id. | |
// | |
DataSize = sizeof (EFI_IP6_CONFIG_INTERFACE_ID); | |
ZeroMem (&Ip6NvData->InterfaceId, DataSize); | |
Status = Ip6Config->GetData ( | |
Ip6Config, | |
Ip6ConfigDataTypeAltInterfaceId, | |
&DataSize, | |
&Ip6NvData->InterfaceId | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
Ip6ConvertInterfaceIdToString (IfrNvData->InterfaceId, &Ip6NvData->InterfaceId); | |
// | |
// Get current policy. | |
// | |
DataSize = sizeof (EFI_IP6_CONFIG_POLICY); | |
Status = Ip6Config->GetData ( | |
Ip6Config, | |
Ip6ConfigDataTypePolicy, | |
&DataSize, | |
&Policy | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
if (Policy == Ip6ConfigPolicyManual) { | |
IfrNvData->Policy = IP6_POLICY_MANUAL; | |
} else if (Policy == Ip6ConfigPolicyAutomatic) { | |
IfrNvData->Policy = IP6_POLICY_AUTO; | |
} else { | |
ASSERT (FALSE); | |
Status = EFI_UNSUPPORTED; | |
goto Exit; | |
} | |
// | |
// Get Duplicate Address Detection Transmits count. | |
// | |
DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS); | |
Status = Ip6Config->GetData ( | |
Ip6Config, | |
Ip6ConfigDataTypeDupAddrDetectTransmits, | |
&DataSize, | |
&DadXmits | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
IfrNvData->DadTransmitCount = DadXmits.DupAddrDetectTransmits; | |
Exit: | |
if (Data != NULL) { | |
FreePool (Data); | |
} | |
return Status; | |
} | |
/** | |
Convert IFR data into IP6 configuration data. The policy, alternative interface | |
ID, and DAD transmit counts, and will be saved. | |
@param[in] IfrNvData The IFR NV data. | |
@param[in, out] Instance The IP6 config instance data. | |
@retval EFI_SUCCESS The operation finished successfully. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
@retval Others Other errors as indicated. | |
**/ | |
EFI_STATUS | |
Ip6ConvertIfrNvDataToConfigNvDataGeneral ( | |
IN IP6_CONFIG_IFR_NVDATA *IfrNvData, | |
IN OUT IP6_CONFIG_INSTANCE *Instance | |
) | |
{ | |
IP6_CONFIG_NVDATA *Ip6NvData; | |
EFI_IP6_CONFIG_PROTOCOL *Ip6Config; | |
EFI_STATUS Status; | |
if ((IfrNvData == NULL) || (Instance == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE); | |
Ip6NvData = &Instance->Ip6NvData; | |
Ip6Config = &Instance->Ip6Config; | |
// | |
// Update those fields which don't have INTERACTIVE attribute. | |
// | |
if (IfrNvData->Policy == IP6_POLICY_AUTO) { | |
Ip6NvData->Policy = Ip6ConfigPolicyAutomatic; | |
} else if (IfrNvData->Policy == IP6_POLICY_MANUAL) { | |
Ip6NvData->Policy = Ip6ConfigPolicyManual; | |
} | |
Ip6NvData->DadTransmitCount.DupAddrDetectTransmits = IfrNvData->DadTransmitCount; | |
// | |
// Set the configured policy. | |
// | |
Status = Ip6Config->SetData ( | |
Ip6Config, | |
Ip6ConfigDataTypePolicy, | |
sizeof (EFI_IP6_CONFIG_POLICY), | |
&Ip6NvData->Policy | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
// | |
// Set the duplicate address detection transmits count. | |
// | |
Status = Ip6Config->SetData ( | |
Ip6Config, | |
Ip6ConfigDataTypeDupAddrDetectTransmits, | |
sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS), | |
&Ip6NvData->DadTransmitCount | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
// | |
// Set the alternative interface ID | |
// | |
Status = Ip6Config->SetData ( | |
Ip6Config, | |
Ip6ConfigDataTypeAltInterfaceId, | |
sizeof (EFI_IP6_CONFIG_INTERFACE_ID), | |
&Ip6NvData->InterfaceId | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Convert IFR data into IP6 configuration data. The policy, configured | |
manual address, gateway address, and DNS server address will be saved. | |
@param[in] IfrNvData The IFR NV data. | |
@param[in, out] Instance The IP6 config instance data. | |
@retval EFI_SUCCESS The operation finished successfully. | |
@retval EFI_INVALID_PARAMETER Any input parameter is invalid. | |
@retval Others Other errors as indicated. | |
**/ | |
EFI_STATUS | |
Ip6ConvertIfrNvDataToConfigNvDataAdvanced ( | |
IN IP6_CONFIG_IFR_NVDATA *IfrNvData, | |
IN OUT IP6_CONFIG_INSTANCE *Instance | |
) | |
{ | |
IP6_CONFIG_NVDATA *Ip6NvData; | |
EFI_IP6_CONFIG_PROTOCOL *Ip6Config; | |
EFI_STATUS Status; | |
EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress; | |
EFI_IPv6_ADDRESS *Address; | |
BOOLEAN IsAddressOk; | |
EFI_EVENT SetAddressEvent; | |
EFI_EVENT TimeoutEvent; | |
UINTN DataSize; | |
if ((IfrNvData == NULL) || (Instance == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (IfrNvData->Policy == IP6_POLICY_AUTO) { | |
return EFI_SUCCESS; | |
} | |
NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE); | |
Ip6NvData = &Instance->Ip6NvData; | |
Ip6Config = &Instance->Ip6Config; | |
// | |
// Update those fields which don't have INTERACTIVE attribute. | |
// | |
Ip6NvData->Policy = Ip6ConfigPolicyManual; | |
// | |
// Set the configured policy. | |
// | |
Status = Ip6Config->SetData ( | |
Ip6Config, | |
Ip6ConfigDataTypePolicy, | |
sizeof (EFI_IP6_CONFIG_POLICY), | |
&Ip6NvData->Policy | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
// | |
// Create events & timers for asynchronous settings. | |
// | |
SetAddressEvent = NULL; | |
TimeoutEvent = NULL; | |
ManualAddress = NULL; | |
Address = NULL; | |
Status = gBS->CreateEvent ( | |
EVT_NOTIFY_SIGNAL, | |
TPL_NOTIFY, | |
Ip6ConfigManualAddressNotify, | |
&IsAddressOk, | |
&SetAddressEvent | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
Status = gBS->CreateEvent ( | |
EVT_TIMER, | |
TPL_CALLBACK, | |
NULL, | |
NULL, | |
&TimeoutEvent | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
// | |
// Set the manual address list. This is an asynchronous process. | |
// | |
if (!IsListEmpty (&Ip6NvData->ManualAddress) && (Ip6NvData->ManualAddressCount != 0)) { | |
Status = Ip6BuildNvAddressInfo ( | |
Instance, | |
Ip6ConfigNvHostAddress, | |
(VOID **) &ManualAddress, | |
&DataSize | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
IsAddressOk = FALSE; | |
Status = Ip6Config->RegisterDataNotify ( | |
Ip6Config, | |
Ip6ConfigDataTypeManualAddress, | |
SetAddressEvent | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
Status = Ip6Config->SetData ( | |
Ip6Config, | |
Ip6ConfigDataTypeManualAddress, | |
DataSize, | |
(VOID *) ManualAddress | |
); | |
if (Status == EFI_NOT_READY) { | |
gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000); | |
while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) { | |
if (IsAddressOk) { | |
Status = EFI_SUCCESS; | |
} | |
break; | |
} | |
} | |
Status = Ip6Config->UnregisterDataNotify ( | |
Ip6Config, | |
Ip6ConfigDataTypeManualAddress, | |
SetAddressEvent | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
} | |
// | |
// Set gateway address list. | |
// | |
if (!IsListEmpty (&Ip6NvData->GatewayAddress) && (Ip6NvData->GatewayAddressCount != 0)) { | |
Status = Ip6BuildNvAddressInfo ( | |
Instance, | |
Ip6ConfigNvGatewayAddress, | |
(VOID **) &Address, | |
&DataSize | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
Status = Ip6Config->SetData ( | |
Ip6Config, | |
Ip6ConfigDataTypeGateway, | |
DataSize, | |
(VOID *) Address | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
FreePool (Address); | |
Address = NULL; | |
} | |
// | |
// Set DNS server address list. | |
// | |
if (!IsListEmpty (&Ip6NvData->DnsAddress) && (Ip6NvData->DnsAddressCount != 0)) { | |
Status = Ip6BuildNvAddressInfo ( | |
Instance, | |
Ip6ConfigNvDnsAddress, | |
(VOID **) &Address, | |
&DataSize | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
Status = Ip6Config->SetData ( | |
Ip6Config, | |
Ip6ConfigDataTypeDnsServer, | |
DataSize, | |
(VOID *) Address | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
} | |
Status = EFI_SUCCESS; | |
Exit: | |
if (SetAddressEvent != NULL) { | |
gBS->CloseEvent (SetAddressEvent); | |
} | |
if (TimeoutEvent != NULL) { | |
gBS->CloseEvent (TimeoutEvent); | |
} | |
if (ManualAddress != NULL) { | |
FreePool (ManualAddress); | |
} | |
if (Address != NULL) { | |
FreePool (Address); | |
} | |
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_INVALID_PARAMETER For example, passing in a NULL | |
for the Request parameter | |
would result in this type of | |
error. In this case, the | |
Progress parameter would be | |
set to NULL. | |
@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 | |
Ip6FormExtractConfig ( | |
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
IN CONST EFI_STRING Request, | |
OUT EFI_STRING *Progress, | |
OUT EFI_STRING *Results | |
) | |
{ | |
EFI_STATUS Status; | |
IP6_FORM_CALLBACK_INFO *Private; | |
IP6_CONFIG_INSTANCE *Ip6ConfigInstance; | |
IP6_CONFIG_IFR_NVDATA *IfrNvData; | |
EFI_STRING ConfigRequestHdr; | |
EFI_STRING ConfigRequest; | |
BOOLEAN AllocatedRequest; | |
UINTN Size; | |
UINTN BufferSize; | |
if (This == NULL || Progress == NULL || Results == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
*Progress = Request; | |
if ((Request != NULL) && | |
!HiiIsConfigHdrMatch (Request, &gIp6ConfigNvDataGuid, mIp6ConfigStorageName)) { | |
return EFI_NOT_FOUND; | |
} | |
ConfigRequestHdr = NULL; | |
ConfigRequest = NULL; | |
AllocatedRequest = FALSE; | |
Size = 0; | |
Private = IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This); | |
Ip6ConfigInstance = IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK (Private); | |
BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA); | |
IfrNvData = (IP6_CONFIG_IFR_NVDATA *) AllocateZeroPool (BufferSize); | |
if (IfrNvData == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Status = Ip6ConvertConfigNvDataToIfrNvData (IfrNvData, Ip6ConfigInstance); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
ConfigRequest = Request; | |
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 ( | |
&gIp6ConfigNvDataGuid, | |
mIp6ConfigStorageName, | |
Private->ChildHandle | |
); | |
Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); | |
ConfigRequest = AllocateZeroPool (Size); | |
ASSERT (ConfigRequest != NULL); | |
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 *) IfrNvData, | |
BufferSize, | |
Results, | |
Progress | |
); | |
Exit: | |
FreePool (IfrNvData); | |
// | |
// Free the allocated config request string. | |
// | |
if (AllocatedRequest) { | |
FreePool (ConfigRequest); | |
ConfigRequest = NULL; | |
} | |
// | |
// 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 | |
beginn ing 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 | |
Ip6FormRouteConfig ( | |
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
IN CONST EFI_STRING Configuration, | |
OUT EFI_STRING *Progress | |
) | |
{ | |
if (This == NULL || Configuration == NULL || Progress == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// Check routing data in <ConfigHdr>. | |
// Note: if only one Storage is used, then this checking could be skipped. | |
// | |
if (!HiiIsConfigHdrMatch (Configuration, &gIp6ConfigNvDataGuid, mIp6ConfigStorageName)) { | |
*Progress = Configuration; | |
return EFI_NOT_FOUND; | |
} | |
*Progress = Configuration + StrLen (Configuration); | |
return EFI_SUCCESS; | |
} | |
/** | |
Display host addresses, route table, DNS addresses and gateway addresses in | |
"IPv6 Current Setting" page. | |
@param[in] Instance The IP6 config instance data. | |
@retval EFI_SUCCESS The operation finished successfully. | |
@retval Others Other errors as indicated. | |
**/ | |
EFI_STATUS | |
Ip6GetCurrentSetting ( | |
IN IP6_CONFIG_INSTANCE *Instance | |
) | |
{ | |
EFI_IP6_CONFIG_PROTOCOL *Ip6Config; | |
EFI_HII_HANDLE HiiHandle; | |
EFI_IP6_CONFIG_INTERFACE_INFO *Data; | |
UINTN DataSize; | |
EFI_STATUS Status; | |
CHAR16 PortString[ADDRESS_STR_MAX_SIZE]; | |
EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo; | |
Ip6Config = &Instance->Ip6Config; | |
HiiHandle = Instance->CallbackInfo.RegisteredHandle; | |
Data = NULL; | |
// | |
// Get current interface info. | |
// | |
Status = Ip6ConfigNvGetData ( | |
Ip6Config, | |
Ip6ConfigDataTypeInterfaceInfo, | |
&DataSize, | |
(VOID **) &Data | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
// | |
// Generate dynamic text opcode for host address and draw it. | |
// | |
IfInfo = (EFI_IP6_CONFIG_INTERFACE_INFO *) Data; | |
Status = Ip6ConvertAddressListToString ( | |
PortString, | |
HiiHandle, | |
Ip6ConfigNvHostAddress, | |
IfInfo->AddressInfo, | |
IfInfo->AddressInfoCount | |
); | |
if (EFI_ERROR (Status)) { | |
FreePool (Data); | |
return Status; | |
} | |
// | |
// Generate the dynamic text opcode for route table and draw it. | |
// | |
Status = Ip6ConvertAddressListToString ( | |
PortString, | |
HiiHandle, | |
Ip6ConfigNvRouteTable, | |
IfInfo->RouteTable, | |
IfInfo->RouteCount | |
); | |
if (EFI_ERROR (Status)) { | |
FreePool (Data); | |
return Status; | |
} | |
// | |
// Get DNS server list. | |
// | |
FreePool (Data); | |
DataSize = 0; | |
Data = NULL; | |
Status = Ip6ConfigNvGetData ( | |
Ip6Config, | |
Ip6ConfigDataTypeDnsServer, | |
&DataSize, | |
(VOID **) &Data | |
); | |
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { | |
if (Data != NULL) { | |
FreePool (Data); | |
} | |
return Status; | |
} | |
if (DataSize > 0) { | |
// | |
// Generate the dynamic text opcode for DNS server and draw it. | |
// | |
Status = Ip6ConvertAddressListToString ( | |
PortString, | |
HiiHandle, | |
Ip6ConfigNvDnsAddress, | |
Data, | |
DataSize / sizeof (EFI_IPv6_ADDRESS) | |
); | |
if (EFI_ERROR (Status)) { | |
FreePool (Data); | |
return Status; | |
} | |
} | |
// | |
// Get gateway adderss list. | |
// | |
if (Data != NULL) { | |
FreePool (Data); | |
} | |
DataSize = 0; | |
Data = NULL; | |
Status = Ip6ConfigNvGetData ( | |
Ip6Config, | |
Ip6ConfigDataTypeGateway, | |
&DataSize, | |
(VOID **) &Data | |
); | |
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { | |
if (Data != NULL) { | |
FreePool (Data); | |
} | |
return Status; | |
} | |
if (DataSize > 0) { | |
// | |
// Generate the dynamic text opcode for gateway and draw it. | |
// | |
Status = Ip6ConvertAddressListToString ( | |
PortString, | |
HiiHandle, | |
Ip6ConfigNvGatewayAddress, | |
Data, | |
DataSize / sizeof (EFI_IPv6_ADDRESS) | |
); | |
if (EFI_ERROR (Status)) { | |
FreePool (Data); | |
return Status; | |
} | |
} | |
if (Data != NULL) { | |
FreePool (Data); | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
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 generated 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_PARAMETER Passed in the wrong parameter. | |
@retval Others Other errors as indicated. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Ip6FormCallback ( | |
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 | |
) | |
{ | |
IP6_FORM_CALLBACK_INFO *Private; | |
UINTN BufferSize; | |
IP6_CONFIG_IFR_NVDATA *IfrNvData; | |
EFI_STATUS Status; | |
EFI_INPUT_KEY Key; | |
IP6_CONFIG_INSTANCE *Instance; | |
IP6_CONFIG_NVDATA *Ip6NvData; | |
if (This == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Private = IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This); | |
Instance = IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK (Private); | |
Ip6NvData = &Instance->Ip6NvData; | |
if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)){ | |
return EFI_SUCCESS; | |
} | |
if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { | |
return EFI_UNSUPPORTED; | |
} | |
if ((Value == NULL) || (ActionRequest == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// Retrieve uncommitted data from Browser | |
// | |
BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA); | |
IfrNvData = AllocateZeroPool (BufferSize); | |
if (IfrNvData == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Status = EFI_SUCCESS; | |
HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData); | |
if (Action == EFI_BROWSER_ACTION_CHANGING) { | |
switch (QuestionId) { | |
case KEY_GET_CURRENT_SETTING: | |
Status = Ip6GetCurrentSetting (Instance); | |
break; | |
default: | |
break; | |
} | |
} else if (Action == EFI_BROWSER_ACTION_CHANGED) { | |
switch (QuestionId) { | |
case KEY_SAVE_CONFIG_CHANGES: | |
Status = Ip6ConvertIfrNvDataToConfigNvDataAdvanced (IfrNvData, Instance); | |
if (EFI_ERROR (Status)) { | |
break; | |
} | |
Status = Ip6GetCurrentSetting (Instance); | |
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; | |
break; | |
case KEY_IGNORE_CONFIG_CHANGES: | |
Ip6FreeAddressInfoList (&Ip6NvData->ManualAddress); | |
Ip6FreeAddressInfoList (&Ip6NvData->GatewayAddress); | |
Ip6FreeAddressInfoList (&Ip6NvData->DnsAddress); | |
Ip6NvData->ManualAddressCount = 0; | |
Ip6NvData->GatewayAddressCount = 0; | |
Ip6NvData->DnsAddressCount = 0; | |
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; | |
break; | |
case KEY_SAVE_CHANGES: | |
Status = Ip6ConvertIfrNvDataToConfigNvDataGeneral (IfrNvData, Instance); | |
if (EFI_ERROR (Status)) { | |
break; | |
} | |
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; | |
break; | |
case KEY_INTERFACE_ID: | |
Status = Ip6ParseInterfaceIdFromString (IfrNvData->InterfaceId, &Ip6NvData->InterfaceId); | |
if (EFI_ERROR (Status)) { | |
CreatePopUp ( | |
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, | |
&Key, | |
L"Invalid Interface ID!", | |
NULL | |
); | |
} | |
break; | |
case KEY_MANUAL_ADDRESS: | |
Status = Ip6ParseAddressListFromString ( | |
IfrNvData->ManualAddress, | |
&Ip6NvData->ManualAddress, | |
&Ip6NvData->ManualAddressCount | |
); | |
if (EFI_ERROR (Status)) { | |
CreatePopUp ( | |
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, | |
&Key, | |
L"Invalid Host Addresses!", | |
NULL | |
); | |
} | |
break; | |
case KEY_GATEWAY_ADDRESS: | |
Status = Ip6ParseAddressListFromString ( | |
IfrNvData->GatewayAddress, | |
&Ip6NvData->GatewayAddress, | |
&Ip6NvData->GatewayAddressCount | |
); | |
if (EFI_ERROR (Status)) { | |
CreatePopUp ( | |
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, | |
&Key, | |
L"Invalid Gateway Addresses!", | |
NULL | |
); | |
} | |
break; | |
case KEY_DNS_ADDRESS: | |
Status = Ip6ParseAddressListFromString ( | |
IfrNvData->DnsAddress, | |
&Ip6NvData->DnsAddress, | |
&Ip6NvData->DnsAddressCount | |
); | |
if (EFI_ERROR (Status)) { | |
CreatePopUp ( | |
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, | |
&Key, | |
L"Invalid DNS Addresses!", | |
NULL | |
); | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
if (!EFI_ERROR (Status)) { | |
// | |
// Pass changed uncommitted data back to Form Browser. | |
// | |
BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA); | |
HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL); | |
} | |
FreePool (IfrNvData); | |
return Status; | |
} | |
/** | |
Install HII Config Access protocol for network device and allocate resources. | |
@param[in, out] Instance The IP6_CONFIG_INSTANCE to create a form. | |
@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 | |
Ip6ConfigFormInit ( | |
IN OUT IP6_CONFIG_INSTANCE *Instance | |
) | |
{ | |
EFI_STATUS Status; | |
IP6_SERVICE *IpSb; | |
IP6_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 = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance); | |
ASSERT (IpSb != NULL); | |
Status = gBS->HandleProtocol ( | |
IpSb->Controller, | |
&gEfiDevicePathProtocolGuid, | |
(VOID **) &ParentDevicePath | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
CallbackInfo = &Instance->CallbackInfo; | |
CallbackInfo->Signature = IP6_FORM_CALLBACK_INFO_SIGNATURE; | |
// | |
// 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->HiiConfigAccess; | |
ConfigAccess->ExtractConfig = Ip6FormExtractConfig; | |
ConfigAccess->RouteConfig = Ip6FormRouteConfig; | |
ConfigAccess->Callback = Ip6FormCallback; | |
// | |
// 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 ( | |
&gIp6ConfigNvDataGuid, | |
CallbackInfo->ChildHandle, | |
Ip6DxeStrings, | |
Ip6ConfigBin, | |
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_IP6_CONFIG_FORM_HELP), | |
NULL) | |
; | |
UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString); | |
HiiSetString ( | |
CallbackInfo->RegisteredHandle, | |
STRING_TOKEN (STR_IP6_CONFIG_FORM_HELP), | |
MenuString, | |
NULL | |
); | |
UnicodeSPrint (PortString, 128, L"MAC:%s", MacString); | |
HiiSetString ( | |
CallbackInfo->RegisteredHandle, | |
STRING_TOKEN (STR_IP6_DEVICE_FORM_HELP), | |
PortString, | |
NULL | |
); | |
FreePool (MacString); | |
FreePool (OldMenuString); | |
InitializeListHead (&Instance->Ip6NvData.ManualAddress); | |
InitializeListHead (&Instance->Ip6NvData.GatewayAddress); | |
InitializeListHead (&Instance->Ip6NvData.DnsAddress); | |
return EFI_SUCCESS; | |
} | |
Error: | |
Ip6ConfigFormUnload (Instance); | |
return Status; | |
} | |
/** | |
Uninstall the HII Config Access protocol for network devices and free up the resources. | |
@param[in, out] Instance The IP6_CONFIG_INSTANCE to unload a form. | |
**/ | |
VOID | |
Ip6ConfigFormUnload ( | |
IN OUT IP6_CONFIG_INSTANCE *Instance | |
) | |
{ | |
IP6_SERVICE *IpSb; | |
IP6_FORM_CALLBACK_INFO *CallbackInfo; | |
IP6_CONFIG_NVDATA *Ip6NvData; | |
IpSb = IP6_SERVICE_FROM_IP6_CONFIG_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->HiiConfigAccess, | |
NULL | |
); | |
} | |
if (CallbackInfo->HiiVendorDevicePath != NULL) { | |
FreePool (CallbackInfo->HiiVendorDevicePath); | |
} | |
if (CallbackInfo->RegisteredHandle != NULL) { | |
// | |
// Remove HII package list | |
// | |
HiiRemovePackages (CallbackInfo->RegisteredHandle); | |
} | |
Ip6NvData = &Instance->Ip6NvData; | |
Ip6FreeAddressInfoList (&Ip6NvData->ManualAddress); | |
Ip6FreeAddressInfoList (&Ip6NvData->GatewayAddress); | |
Ip6FreeAddressInfoList (&Ip6NvData->DnsAddress); | |
Ip6NvData->ManualAddressCount = 0; | |
Ip6NvData->GatewayAddressCount = 0; | |
Ip6NvData->DnsAddressCount = 0; | |
} |