mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-25 16:37:42 +01:00
15dada20e6
Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
2090 lines
64 KiB
C
2090 lines
64 KiB
C
/** @file
|
|
Helper functions for configuring or obtaining the parameters relating to IP6.
|
|
|
|
Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#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;
|
|
}
|