| /** @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; | |
| } |