From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../WifiConnectionMgrHiiConfigAccess.c | 2017 ++++++++++++++++++++ 1 file changed, 2017 insertions(+) create mode 100644 src/VBox/Devices/EFI/Firmware/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.c (limited to 'src/VBox/Devices/EFI/Firmware/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.c') diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.c b/src/VBox/Devices/EFI/Firmware/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.c new file mode 100644 index 00000000..73fce8a8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.c @@ -0,0 +1,2017 @@ +/** @file + The Hii functions for WiFi Connection Manager. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "WifiConnectionMgrDxe.h" + +CHAR16 mVendorStorageName[] = L"WIFI_MANAGER_IFR_NVDATA"; + +HII_VENDOR_DEVICE_PATH mWifiMgrDxeHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + WIFI_CONNECTION_MANAGER_CONFIG_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +// +// HII Config Access Protocol instance +// +GLOBAL_REMOVE_IF_UNREFERENCED +EFI_HII_CONFIG_ACCESS_PROTOCOL gWifiMgrDxeHiiConfigAccess = { + WifiMgrDxeHiiConfigAccessExtractConfig, + WifiMgrDxeHiiConfigAccessRouteConfig, + WifiMgrDxeHiiConfigAccessCallback +}; + +CHAR16* mSecurityType[] = { + L"OPEN ", + L"WPA-Enterprise ", + L"WPA2-Enterprise", + L"WPA-Personal ", + L"WPA2-Personal ", + L"WEP ", + L"UnKnown " +}; + +CHAR16* mSignalStrengthBar[] = { + L"[-----]", + L"[*----]", + L"[**---]", + L"[***--]", + L"[****-]", + L"[*****]" +}; + +#define RSSI_TO_SIGNAL_STRENGTH_BAR(Rssi) mSignalStrengthBar[((Rssi + 19)/20)] + +#define NET_LIST_FOR_EACH_FROM_NODE(Entry, Node, ListHead) \ + for(Entry = Node->ForwardLink; Entry != (ListHead); Entry = Entry->ForwardLink) + +extern EFI_GUID gWifiConfigFormSetGuid; + +/** + Create Hii Extend Label OpCode as the start opcode and end opcode. + The caller is responsible for freeing the OpCode with HiiFreeOpCodeHandle(). + + @param[in] StartLabelNumber The number of start label. + @param[out] StartOpCodeHandle Points to the start opcode handle. + @param[out] EndOpCodeHandle Points to the end opcode handle. + + @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this + operation. + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_SUCCESS The operation is completed successfully. + @retval Other Errors Returned errors when updating the HII form. + +**/ +EFI_STATUS +WifiMgrCreateOpCode ( + IN UINT16 StartLabelNumber, + OUT VOID **StartOpCodeHandle, + OUT VOID **EndOpCodeHandle + ) +{ + EFI_STATUS Status; + EFI_IFR_GUID_LABEL *InternalStartLabel; + EFI_IFR_GUID_LABEL *InternalEndLabel; + + if (StartOpCodeHandle == NULL || EndOpCodeHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_OUT_OF_RESOURCES; + *StartOpCodeHandle = NULL; + *EndOpCodeHandle = NULL; + + // + // Initialize the container for dynamic opcodes. + // + *StartOpCodeHandle = HiiAllocateOpCodeHandle (); + if (*StartOpCodeHandle == NULL) { + goto Exit; + } + *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; + + return EFI_SUCCESS; + +Exit: + + if (*StartOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (*StartOpCodeHandle); + } + if (*EndOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (*EndOpCodeHandle); + } + return Status; +} + +/** + Display the Nic list contains all available Nics. + + @param[in] Private The pointer to the global private data structure. + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_SUCCESS The operation is completed successfully. + +**/ +EFI_STATUS +WifiMgrShowNicList ( + IN WIFI_MGR_PRIVATE_DATA *Private +) +{ + EFI_STATUS Status; + CHAR16 MacString[WIFI_MGR_MAX_MAC_STRING_LEN]; + CHAR16 PortString[WIFI_STR_MAX_SIZE]; + EFI_STRING_ID PortTitleToken; + EFI_STRING_ID PortTitleHelpToken; + WIFI_MGR_DEVICE_DATA *Nic; + LIST_ENTRY *Entry; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + + if (Private == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = WifiMgrCreateOpCode ( + LABEL_MAC_ENTRY, + &StartOpCodeHandle, + &EndOpCodeHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + NET_LIST_FOR_EACH (Entry, &Private->NicList) { + Nic = NET_LIST_USER_STRUCT_S (Entry, WIFI_MGR_DEVICE_DATA, Link, WIFI_MGR_DEVICE_DATA_SIGNATURE); + WifiMgrMacAddrToStr (&Nic->MacAddress, sizeof (MacString), MacString); + UnicodeSPrint (PortString, sizeof (PortString), L"MAC %s", MacString); + PortTitleToken = HiiSetString ( + Private->RegisteredHandle, + 0, + PortString, + NULL + ); + if (PortTitleToken == 0) { + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + UnicodeSPrint (PortString, sizeof (PortString), L"MAC Address"); + PortTitleHelpToken = HiiSetString ( + Private->RegisteredHandle, + 0, + PortString, + NULL + ); + if (PortTitleHelpToken == 0) { + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + HiiCreateGotoOpCode ( + StartOpCodeHandle, + FORMID_WIFI_MAINPAGE, + PortTitleToken, + PortTitleHelpToken, + EFI_IFR_FLAG_CALLBACK, + (UINT16) (KEY_MAC_ENTRY_BASE + Nic->NicIndex) + ); + } + + Status = HiiUpdateForm ( + Private->RegisteredHandle, // HII handle + &gWifiConfigFormSetGuid, // Formset GUID + FORMID_MAC_SELECTION, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + +Exit: + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + return Status; +} + +/** + Retreive the unicode string of the AKM Suite list of a profile. + The caller is responsible for freeing the string with FreePool(). + + @param[in] Profile The network profile contains a AKM suite list. + + @return the unicode string of AKM suite list or "None". + +**/ +CHAR16* +WifiMgrGetStrAKMList ( + IN WIFI_MGR_NETWORK_PROFILE *Profile +) +{ + UINT8 Index; + UINT16 AKMSuiteCount; + CHAR16 *AKMListDisplay; + + AKMListDisplay = NULL; + if (Profile == NULL || Profile->Network.AKMSuite == NULL) { + goto Exit; + } + + AKMSuiteCount = Profile->Network.AKMSuite->AKMSuiteCount; + if (AKMSuiteCount != 0) { + + // + // Current AKM Suite is between 1-9 + // + AKMListDisplay = (CHAR16 *) AllocateZeroPool(sizeof (CHAR16) * AKMSuiteCount * 2); + if (AKMListDisplay != NULL) { + for (Index = 0; Index < AKMSuiteCount; Index ++) { + UnicodeSPrint ( + AKMListDisplay + (Index * 2), + sizeof (CHAR16) * 2, + L"%d ", + Profile->Network.AKMSuite->AKMSuiteList[Index].SuiteType + ); + if (Index == AKMSuiteCount - 1) { + *(AKMListDisplay + (Index * 2 + 1)) = L'\0'; + } + } + } + } + +Exit: + + if (AKMListDisplay == NULL) { + AKMListDisplay = AllocateCopyPool (sizeof (L"None"), L"None"); + } + return AKMListDisplay; +} + +/** + Retreive the unicode string of the Cipher Suite list of a profile. + The caller is responsible for freeing the string with FreePool(). + + @param[in] Profile The network profile contains a Cipher suite list. + + @return the unicode string of Cipher suite list or "None". + +**/ +CHAR16* +WifiMgrGetStrCipherList ( + IN WIFI_MGR_NETWORK_PROFILE *Profile +) +{ + UINT8 Index; + UINT16 CipherSuiteCount; + CHAR16 *CipherListDisplay; + + CipherListDisplay = NULL; + if (Profile == NULL || Profile->Network.CipherSuite == NULL) { + goto Exit; + } + + CipherSuiteCount = Profile->Network.CipherSuite->CipherSuiteCount; + if (CipherSuiteCount != 0) { + + // + // Current Cipher Suite is between 1-9 + // + CipherListDisplay = (CHAR16 *) AllocateZeroPool(sizeof (CHAR16) * CipherSuiteCount * 2); + if (CipherListDisplay != NULL) { + for (Index = 0; Index < CipherSuiteCount; Index ++) { + UnicodeSPrint ( + CipherListDisplay + (Index * 2), + sizeof (CHAR16) * 2, + L"%d ", + Profile->Network.CipherSuite->CipherSuiteList[Index].SuiteType + ); + if (Index == CipherSuiteCount - 1) { + *(CipherListDisplay + (Index * 2 + 1)) = L'\0'; + } + } + } + } + +Exit: + + if (CipherListDisplay == NULL) { + CipherListDisplay = AllocateCopyPool (sizeof (L"None"), L"None"); + } + return CipherListDisplay; +} + +/** + Refresh the network list display of the current Nic. + + @param[in] Private The pointer to the global private data structure. + @param[out] IfrNvData The IFR NV data. + + @retval EFI_SUCCESS The operation is completed successfully. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. + @retval Other Errors Returned errors when creating Opcodes or updating the + Hii form. + +**/ +EFI_STATUS +WifiMgrRefreshNetworkList ( + IN WIFI_MGR_PRIVATE_DATA *Private, + OUT WIFI_MANAGER_IFR_NVDATA *IfrNvData + ) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + UINT32 AvailableCount; + EFI_STRING_ID PortPromptToken; + EFI_STRING_ID PortTextToken; + EFI_STRING_ID PortHelpToken; + WIFI_MGR_NETWORK_PROFILE *Profile; + LIST_ENTRY *Entry; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + CHAR16 *AKMListDisplay; + CHAR16 *CipherListDisplay; + CHAR16 PortString[WIFI_STR_MAX_SIZE]; + UINTN PortStringSize; + WIFI_MGR_NETWORK_PROFILE *ConnectedProfile; + + if (Private->CurrentNic == NULL) { + return EFI_SUCCESS; + } + + Status = WifiMgrCreateOpCode ( + LABEL_NETWORK_LIST_ENTRY, + &StartOpCodeHandle, + &EndOpCodeHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + AvailableCount = 0; + PortStringSize = sizeof (PortString); + ConnectedProfile = NULL; + AKMListDisplay = NULL; + CipherListDisplay = NULL; + + if (Private->CurrentNic->ConnectState == WifiMgrConnectedToAp) { + + // + // Display the current connected network. + // Find the current operate network under connected status. + // + if (Private->CurrentNic->CurrentOperateNetwork != NULL && + Private->CurrentNic->CurrentOperateNetwork->IsAvailable) { + + Profile = Private->CurrentNic->CurrentOperateNetwork; + AvailableCount ++; + + AKMListDisplay = WifiMgrGetStrAKMList (Profile); + if (AKMListDisplay == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + CipherListDisplay = WifiMgrGetStrCipherList(Profile); + if (CipherListDisplay == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + UnicodeSPrint (PortString, PortStringSize, L"%s (Connected)", Profile->SSId); + PortPromptToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL); + + if (Profile->SecurityType == SECURITY_TYPE_NONE) { + PortHelpToken = 0; + } else { + UnicodeSPrint (PortString, PortStringSize, L"AKMSuite: %s CipherSuite: %s", AKMListDisplay, CipherListDisplay); + PortHelpToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL); + } + FreePool (AKMListDisplay); + FreePool (CipherListDisplay); + AKMListDisplay = NULL; + CipherListDisplay = NULL; + + HiiCreateGotoOpCode ( + StartOpCodeHandle, + FORMID_CONNECT_NETWORK, + PortPromptToken, + PortHelpToken, + EFI_IFR_FLAG_CALLBACK, + (UINT16) (KEY_AVAILABLE_NETWORK_ENTRY_BASE + Profile->ProfileIndex) + ); + + UnicodeSPrint ( + PortString, + PortStringSize, + L"%s %s %s", + (Profile->SecurityType != SECURITY_TYPE_NONE ? L"Secured" : L"Open "), + mSecurityType[Profile->SecurityType], + RSSI_TO_SIGNAL_STRENGTH_BAR(Profile->NetworkQuality) + ); + PortTextToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL); + + HiiCreateTextOpCode ( + StartOpCodeHandle, + PortTextToken, + 0, + 0 + ); + + ConnectedProfile = Profile; + } else { + Private->CurrentNic->HasDisconnectPendingNetwork = TRUE; + } + } + + // + // Display all supported available networks. + // + NET_LIST_FOR_EACH (Entry, &Private->CurrentNic->ProfileList) { + + Profile = NET_LIST_USER_STRUCT_S ( + Entry, + WIFI_MGR_NETWORK_PROFILE, + Link, + WIFI_MGR_PROFILE_SIGNATURE + ); + if (ConnectedProfile == Profile) { + continue; + } + if (Profile->IsAvailable && Profile->CipherSuiteSupported) { + + AvailableCount ++; + + AKMListDisplay = WifiMgrGetStrAKMList (Profile); + if (AKMListDisplay == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + CipherListDisplay = WifiMgrGetStrCipherList(Profile); + if (CipherListDisplay == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + PortPromptToken = HiiSetString (Private->RegisteredHandle, 0, Profile->SSId, NULL); + if (PortPromptToken == 0) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + if (Profile->SecurityType == SECURITY_TYPE_NONE) { + PortHelpToken = 0; + } else { + UnicodeSPrint ( + PortString, + PortStringSize, + L"AKMSuite: %s CipherSuite: %s", + AKMListDisplay, CipherListDisplay + ); + PortHelpToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL); + if (PortHelpToken == 0) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + } + FreePool (AKMListDisplay); + FreePool (CipherListDisplay); + AKMListDisplay = NULL; + CipherListDisplay = NULL; + + HiiCreateGotoOpCode ( + StartOpCodeHandle, + FORMID_CONNECT_NETWORK, + PortPromptToken, + PortHelpToken, + EFI_IFR_FLAG_CALLBACK, + (UINT16) (KEY_AVAILABLE_NETWORK_ENTRY_BASE + Profile->ProfileIndex) + ); + + UnicodeSPrint ( + PortString, + PortStringSize, + L"%s %s %s", + (Profile->SecurityType != SECURITY_TYPE_NONE ? L"Secured" : L"Open "), + mSecurityType[Profile->SecurityType], + RSSI_TO_SIGNAL_STRENGTH_BAR(Profile->NetworkQuality) + ); + PortTextToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL); + if (PortTextToken == 0) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + HiiCreateTextOpCode ( + StartOpCodeHandle, + PortTextToken, + 0, + 0 + ); + } + } + + // + // Display all Unsupported available networks. + // + NET_LIST_FOR_EACH (Entry, &Private->CurrentNic->ProfileList) { + + Profile = NET_LIST_USER_STRUCT_S ( + Entry, + WIFI_MGR_NETWORK_PROFILE, + Link, + WIFI_MGR_PROFILE_SIGNATURE + ); + if (ConnectedProfile == Profile) { + continue; + } + if (Profile->IsAvailable && !Profile->CipherSuiteSupported) { + + AvailableCount ++; + + AKMListDisplay = WifiMgrGetStrAKMList (Profile); + if (AKMListDisplay == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + CipherListDisplay = WifiMgrGetStrCipherList(Profile); + if (CipherListDisplay == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + PortPromptToken = HiiSetString (Private->RegisteredHandle, 0, Profile->SSId, NULL); + + if (Profile->AKMSuiteSupported) { + UnicodeSPrint ( + PortString, + PortStringSize, + L"AKMSuite: %s CipherSuite(UnSupported): %s", + AKMListDisplay, CipherListDisplay + ); + } else { + UnicodeSPrint ( + PortString, + PortStringSize, + L"AKMSuite(UnSupported): %s CipherSuite(UnSupported): %s", + AKMListDisplay, CipherListDisplay + ); + } + FreePool (AKMListDisplay); + FreePool (CipherListDisplay); + AKMListDisplay = NULL; + CipherListDisplay = NULL; + + PortHelpToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL); + + HiiCreateGotoOpCode ( + StartOpCodeHandle, + FORMID_CONNECT_NETWORK, + PortPromptToken, + PortHelpToken, + EFI_IFR_FLAG_CALLBACK, + (UINT16) (KEY_AVAILABLE_NETWORK_ENTRY_BASE + Profile->ProfileIndex) + ); + + UnicodeSPrint ( + PortString, + PortStringSize, + L"%s %s %s", + L"UnSupported", + mSecurityType[Profile->SecurityType], + RSSI_TO_SIGNAL_STRENGTH_BAR(Profile->NetworkQuality) + ); + PortTextToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL); + + HiiCreateTextOpCode ( + StartOpCodeHandle, + PortTextToken, + 0, + 0 + ); + } + } + + Status = HiiUpdateForm ( + Private->RegisteredHandle, // HII handle + &gWifiConfigFormSetGuid, // Formset GUID + FORMID_NETWORK_LIST, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + +Exit: + + gBS->RestoreTPL (OldTpl); + + if (AKMListDisplay != NULL) { + FreePool (AKMListDisplay); + } + if (CipherListDisplay != NULL) { + FreePool (CipherListDisplay); + } + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + + DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Network List is Refreshed!\n")); + return Status; +} + +/** + Refresh the hidden network list configured by user. + + @param[in] Private The pointer to the global private data structure. + + @retval EFI_SUCCESS The operation is completed successfully. + @retval Other Errors Returned errors when creating Opcodes or updating the + Hii form. +**/ +EFI_STATUS +WifiMgrRefreshHiddenList ( + IN WIFI_MGR_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + UINTN Index; + EFI_STRING_ID StringId; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + WIFI_HIDDEN_NETWORK_DATA *HiddenNetwork; + LIST_ENTRY *Entry; + + if (Private == NULL) { + return EFI_SUCCESS; + } + + Status = WifiMgrCreateOpCode ( + LABEL_HIDDEN_NETWORK_ENTRY, + &StartOpCodeHandle, + &EndOpCodeHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + Index = 0; + + NET_LIST_FOR_EACH (Entry, &Private->HiddenNetworkList) { + + HiddenNetwork = NET_LIST_USER_STRUCT_S ( + Entry, + WIFI_HIDDEN_NETWORK_DATA, + Link, + WIFI_MGR_HIDDEN_NETWORK_SIGNATURE + ); + StringId = HiiSetString (Private->RegisteredHandle, 0, HiddenNetwork->SSId, NULL); + + HiiCreateCheckBoxOpCode ( + StartOpCodeHandle, + (EFI_QUESTION_ID) (KEY_HIDDEN_NETWORK_ENTRY_BASE + Index), + MANAGER_VARSTORE_ID, + (UINT16) (HIDDEN_NETWORK_LIST_VAR_OFFSET + Index), + StringId, + 0, + 0, + 0, + NULL + ); + Index ++; + } + + Status = HiiUpdateForm ( + Private->RegisteredHandle, // HII handle + &gWifiConfigFormSetGuid, // Formset GUID + FORMID_HIDDEN_NETWORK_LIST, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + gBS->RestoreTPL (OldTpl); + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + return Status; +} + + +/** + Callback function for user to select a Nic. + + @param[in] Private The pointer to the global private data structure. + @param[in] KeyValue The key value received from HII input. + + @retval EFI_NOT_FOUND The corresponding Nic is not found. + @retval EFI_SUCCESS The operation is completed successfully. + +**/ +EFI_STATUS +WifiMgrSelectNic ( + IN WIFI_MGR_PRIVATE_DATA *Private, + IN EFI_QUESTION_ID KeyValue + ) +{ + WIFI_MGR_DEVICE_DATA *Nic; + UINT32 NicIndex; + CHAR16 MacString[WIFI_MGR_MAX_MAC_STRING_LEN]; + + NicIndex = KeyValue - KEY_MAC_ENTRY_BASE; + Nic = WifiMgrGetNicByIndex (Private, NicIndex); + if (Nic == NULL) { + return EFI_NOT_FOUND; + } + Private->CurrentNic = Nic; + + WifiMgrMacAddrToStr (&Nic->MacAddress, sizeof (MacString), MacString); + HiiSetString (Private->RegisteredHandle, STRING_TOKEN(STR_MAC_ADDRESS), MacString, NULL); + return EFI_SUCCESS; +} + +/** + Restore the NV data to be default. + + @param[in] Private The pointer to the global private data structure. + @param[out] IfrNvData The IFR NV data. + +**/ +VOID +WifiMgrCleanUserInput ( + IN WIFI_MGR_PRIVATE_DATA *Private + ) +{ + Private->SecurityType = SECURITY_TYPE_NONE; + Private->EapAuthMethod = EAP_AUTH_METHOD_TTLS; + Private->EapSecondAuthMethod = EAP_SEAUTH_METHOD_MSCHAPV2; + Private->FileType = FileTypeMax; +} + +/** + UI handle function when user select a network to connect. + + @param[in] Private The pointer to the global private data structure. + @param[in] ProfileIndex The profile index user selected to connect. + + @retval EFI_INVALID_PARAMETER Nic is null. + @retval EFI_NOT_FOUND Profile could not be found. + @retval EFI_SUCCESS The operation is completed successfully. + +**/ +EFI_STATUS +WifiMgrUserSelectProfileToConnect( + IN WIFI_MGR_PRIVATE_DATA *Private, + IN UINT32 ProfileIndex + ) +{ + WIFI_MGR_NETWORK_PROFILE *Profile; + WIFI_MGR_DEVICE_DATA *Nic; + + Nic = Private->CurrentNic; + if (Nic == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + //Initialize the connection page + // + WifiMgrCleanUserInput(Private); + + Profile = WifiMgrGetProfileByProfileIndex (ProfileIndex, &Nic->ProfileList); + if (Profile == NULL) { + return EFI_NOT_FOUND; + } + Private->CurrentNic->UserSelectedProfile = Profile; + + return EFI_SUCCESS; +} + +/** + Record password from a HII input string. + + @param[in] Private The pointer to the global private data structure. + @param[in] StringId The QuestionId received from HII input. + @param[in] StringBuffer The unicode string buffer to store password. + @param[in] StringBufferLen The len of unicode string buffer. + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_NOT_FOUND The password string is not found or invalid. + @retval EFI_SUCCESS The operation is completed successfully. + +**/ +EFI_STATUS +WifiMgrRecordPassword ( + IN WIFI_MGR_PRIVATE_DATA *Private, + IN EFI_STRING_ID StringId, + IN CHAR16 *StringBuffer, + IN UINTN StringBufferLen + ) +{ + CHAR16 *Password; + + if (StringId == 0 || StringBuffer == NULL || StringBufferLen <= 0) { + return EFI_INVALID_PARAMETER; + } + + Password = HiiGetString (Private->RegisteredHandle, StringId, NULL); + if (Password == NULL) { + return EFI_NOT_FOUND; + } + if (StrLen (Password) > StringBufferLen) { + FreePool (Password); + return EFI_NOT_FOUND; + } + StrnCpyS (StringBuffer, StringBufferLen, Password, StrLen (Password)); + ZeroMem (Password, (StrLen (Password) + 1) * sizeof (CHAR16)); + FreePool (Password); + + // + // Clean password in string package + // + HiiSetString (Private->RegisteredHandle, StringId, L"", NULL); + return EFI_SUCCESS; +} + +/** + Update connection message on connect configuration page, and trigger related form refresh. + + @param[in] Nic The related Nic for updating message. + @param[in] ConnectStateChanged The tag to tell if the connection state has been changed, only + when the connection changes from "Connected" or "Disconnecting" + to "Disconnected", or from "Disconnected" or "Connecting" to + "Connected", this tag can be set as TRUE. + @param[in] ConnectStatusMessage The message to show on connected status bar, if NULL, will + use default message. + +**/ +VOID +WifiMgrUpdateConnectMessage ( + IN WIFI_MGR_DEVICE_DATA *Nic, + IN BOOLEAN ConnectStateChanged, + IN EFI_STRING ConnectStatusMessage + ) +{ + CHAR16 ConnectStatusStr[WIFI_STR_MAX_SIZE]; + WIFI_MGR_PRIVATE_DATA *Private; + + Private = Nic->Private; + if (Private == NULL || Private->CurrentNic != Nic) { + return; + } + + // + // Update Connection Status Bar + // + if (ConnectStatusMessage != NULL) { + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusMessage, NULL); + } else { + if (Nic->ConnectState == WifiMgrConnectedToAp) { + + UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr), L"Connected to %s", + Nic->CurrentOperateNetwork->SSId); + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusStr, NULL); + } else if (Nic->ConnectState == WifiMgrDisconnected) { + + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), L"Disconnected", NULL); + } else if (Nic->ConnectState == WifiMgrConnectingToAp) { + + UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr), L"Connecting to %s ...", + Nic->CurrentOperateNetwork->SSId); + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusStr, NULL); + } else if (Nic->ConnectState == WifiMgrDisconnectingToAp) { + + UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr), L"Disconnecting from %s ...", + Nic->CurrentOperateNetwork->SSId); + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusStr, NULL); + } else { + return; + } + } + + // + // Update Connect Button + // + if (Nic->ConnectState == WifiMgrConnectedToAp && Nic->UserSelectedProfile == Nic->CurrentOperateNetwork) { + + HiiSetString (Private->RegisteredHandle, + STRING_TOKEN (STR_CONNECT_NOW), L"Disconnect from this Network", NULL); + } else { + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_NOW), L"Connect to this Network", NULL); + } + gBS->SignalEvent (Private->ConnectFormRefreshEvent); + + // + // Update Main Page and Network List + // + if (ConnectStateChanged) { + + if (Nic->ConnectState == WifiMgrConnectedToAp) { + + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECTION_INFO), L"Connected to", NULL); + HiiSetString (Private->RegisteredHandle, + STRING_TOKEN (STR_CONNECTED_SSID), Nic->CurrentOperateNetwork->SSId, NULL); + } else { + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECTION_INFO), L"Disconnected", NULL); + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECTED_SSID), L"", NULL); + } + + gBS->SignalEvent (Private->NetworkListRefreshEvent); + gBS->SignalEvent (Private->MainPageRefreshEvent); + } +} + +/** + Convert the driver configuration data into the IFR data. + + @param[in] Private The pointer to the global private data structure. + @param[out] IfrNvData The IFR NV data. + + @retval EFI_SUCCESS The operation is completed successfully. + +**/ +EFI_STATUS +WifiMgrConvertConfigDataToIfrNvData ( + IN WIFI_MGR_PRIVATE_DATA *Private, + OUT WIFI_MANAGER_IFR_NVDATA *IfrNvData + ) +{ + // + // Private shouldn't be NULL here, assert if Private is NULL. + // + ASSERT (Private != NULL); + + if (Private->CurrentNic != NULL) { + IfrNvData->ProfileCount = Private->CurrentNic->AvailableCount; + } else { + IfrNvData->ProfileCount = 0; + } + + return EFI_SUCCESS; +} + +/** + Convert the IFR data into the driver configuration data. + + @param[in] Private The pointer to the global private data structure. + @param[in, out] IfrNvData The IFR NV data. + + @retval EFI_SUCCESS The operation is completed successfully. + +**/ +EFI_STATUS +WifiMgrConvertIfrNvDataToConfigData ( + IN WIFI_MGR_PRIVATE_DATA *Private, + IN OUT WIFI_MANAGER_IFR_NVDATA *IfrNvData + ) +{ + return EFI_SUCCESS; +} + +/** + This function allows the caller to request the current + configuration for one or more named elements. The resulting + string is in 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=". That (when + converted from Hex UNICODE to binary) is a reference to a + string in the associated string pack. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + + @param Request A null-terminated Unicode string in + 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 + format. + If a NULL is passed in for the Request field, + all of the settings being abstracted by this function + will be returned in the Results field. In addition, + if a ConfigHdr is passed in with no request elements, + all of the settings being abstracted for that particular + ConfigHdr reference will be returned in the Results Field. + + @param 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 Results A null-terminated Unicode string in + format which has all values + filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results string is filled with the + values corresponding to all requested + names. + + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the + parts of the results that must be + stored awaiting possible future + protocols. + + @retval EFI_NOT_FOUND Routing data doesn't match any + known driver. Progress set to the + first character in the routing header. + Note: There is no requirement that the + driver validate the routing data. It + must skip the 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. + +**/ +EFI_STATUS +EFIAPI +WifiMgrDxeHiiConfigAccessExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + WIFI_MGR_PRIVATE_DATA *Private; + WIFI_MANAGER_IFR_NVDATA *IfrNvData; + EFI_STRING ConfigRequestHdr; + EFI_STRING ConfigRequest; + UINTN Size; + BOOLEAN AllocatedRequest; + UINTN BufferSize; + EFI_STATUS Status; + + if (This == NULL || Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Request; + if ((Request != NULL) && + !HiiIsConfigHdrMatch (Request, &gWifiConfigFormSetGuid, mVendorStorageName)) { + return EFI_NOT_FOUND; + } + + ConfigRequestHdr = NULL; + ConfigRequest = NULL; + AllocatedRequest = FALSE; + Size = 0; + + Private = WIFI_MGR_PRIVATE_DATA_FROM_CONFIG_ACCESS (This); + + BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA); + IfrNvData = AllocateZeroPool (BufferSize); + if (IfrNvData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + WifiMgrConvertConfigDataToIfrNvData (Private, IfrNvData); + + 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 template + // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator. + // + ConfigRequestHdr = HiiConstructConfigHdr ( + &gWifiConfigFormSetGuid, + mVendorStorageName, + Private->DriverHandle); + if (ConfigRequestHdr == NULL) { + FreePool (IfrNvData); + return EFI_OUT_OF_RESOURCES; + } + + Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); + ConfigRequest = AllocateZeroPool (Size); + if (ConfigRequest == NULL) { + + FreePool (IfrNvData); + FreePool (ConfigRequestHdr); + return EFI_OUT_OF_RESOURCES; + } + + AllocatedRequest = TRUE; + UnicodeSPrint ( + ConfigRequest, + Size, + L"%s&OFFSET=0&WIDTH=%016LX", + ConfigRequestHdr, + (UINT64) BufferSize + ); + FreePool (ConfigRequestHdr); + } + + // + // Convert buffer data to by helper function BlockToConfig() + // + Status = gHiiConfigRouting->BlockToConfig ( + gHiiConfigRouting, + ConfigRequest, + (UINT8 *) IfrNvData, + BufferSize, + Results, + Progress + ); + + 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 + format, it may use the ConfigToBlock helper function (above) to + simplify the job. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + + @param Configuration A null-terminated Unicode string in + format. + + @param 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_RESOURCES 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 +WifiMgrDxeHiiConfigAccessRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + WIFI_MGR_PRIVATE_DATA *Private; + WIFI_MANAGER_IFR_NVDATA *IfrNvData; + + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + IfrNvData = NULL; + *Progress = Configuration; + BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA); + Private = WIFI_MGR_PRIVATE_DATA_FROM_CONFIG_ACCESS (This); + + if (!HiiIsConfigHdrMatch (Configuration, &gWifiConfigFormSetGuid, mVendorStorageName)) { + return EFI_NOT_FOUND; + } + + IfrNvData = AllocateZeroPool (BufferSize); + if (IfrNvData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + WifiMgrConvertConfigDataToIfrNvData (Private, IfrNvData); + + Status = gHiiConfigRouting->ConfigToBlock ( + gHiiConfigRouting, + Configuration, + (UINT8*) IfrNvData, + &BufferSize, + Progress + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WifiMgrConvertIfrNvDataToConfigData (Private, IfrNvData); + ZeroMem (IfrNvData, sizeof (WIFI_MANAGER_IFR_NVDATA)); + FreePool (IfrNvData); + + return Status; +} + +/** + This function is called to provide results data to the driver. + This data consists of a unique key that is used to identify + which data is either being passed back or being asked for. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param 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 Type The type of value for the question. + @param Value A pointer to the data being sent to the original + exporting driver. + @param 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. + +**/ +EFI_STATUS +EFIAPI +WifiMgrDxeHiiConfigAccessCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN OUT EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + UINTN BufferSize; + WIFI_MGR_PRIVATE_DATA *Private; + WIFI_MANAGER_IFR_NVDATA *IfrNvData; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + WIFI_MGR_NETWORK_PROFILE *Profile; + WIFI_MGR_NETWORK_PROFILE *ProfileToConnect; + WIFI_HIDDEN_NETWORK_DATA *HiddenNetwork; + UINTN TempDataSize; + VOID *TempData; + LIST_ENTRY *Entry; + UINT32 Index; + UINT32 RemoveCount; + CHAR16 *TempPassword; + CHAR16 *ErrorMessage; + + if (Action != EFI_BROWSER_ACTION_FORM_OPEN && + Action != EFI_BROWSER_ACTION_FORM_CLOSE && + Action != EFI_BROWSER_ACTION_CHANGING && + Action != EFI_BROWSER_ACTION_CHANGED && + Action != EFI_BROWSER_ACTION_RETRIEVE) { + + return EFI_UNSUPPORTED; + } + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + Private = WIFI_MGR_PRIVATE_DATA_FROM_CONFIG_ACCESS (This); + if (Private->CurrentNic == NULL) { + return EFI_DEVICE_ERROR; + } + + // + // Retrieve uncommitted data from Browser + // + BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA); + IfrNvData = AllocateZeroPool (BufferSize); + if (IfrNvData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + HiiGetBrowserData (&gWifiConfigFormSetGuid, mVendorStorageName, BufferSize, (UINT8 *) IfrNvData); + + if (Action == EFI_BROWSER_ACTION_FORM_OPEN) { + switch (QuestionId) { + + case KEY_MAC_LIST: + + Status = WifiMgrShowNicList (Private); + break; + + case KEY_REFRESH_NETWORK_LIST: + + if (Private->CurrentNic->UserSelectedProfile != NULL) { + + Profile = Private->CurrentNic->UserSelectedProfile; + + // + // Erase secrets since user has left Connection Page + // Connection Page may direct to Network List Page or Eap Configuration Page, + // secrets only need to be erased when head to Network List Page + // + WifiMgrCleanProfileSecrets (Profile); + + Private->CurrentNic->UserSelectedProfile = NULL; + } + + break; + + case KEY_CONNECT_ACTION: + + if (Private->CurrentNic->UserSelectedProfile == NULL) { + break; + } + Profile = Private->CurrentNic->UserSelectedProfile; + + // + //Enter the network connection configuration page + //Recovery from restored data + // + if (HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_SSID), Profile->SSId, NULL) == 0) { + return EFI_OUT_OF_RESOURCES; + } + IfrNvData->SecurityType = Profile->SecurityType; + if (HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_SECURITY_TYPE), + mSecurityType[IfrNvData->SecurityType], NULL) == 0) { + return EFI_OUT_OF_RESOURCES; + } + + if (IfrNvData->SecurityType == SECURITY_TYPE_WPA2_ENTERPRISE) { + + IfrNvData->EapAuthMethod = Profile->EapAuthMethod; + IfrNvData->EapSecondAuthMethod = Profile->EapSecondAuthMethod; + StrCpyS (IfrNvData->EapIdentity, EAP_IDENTITY_SIZE, Profile->EapIdentity); + } + + break; + + case KEY_ENROLLED_CERT_NAME: + + if (Private->CurrentNic->UserSelectedProfile == NULL) { + break; + } + Profile = Private->CurrentNic->UserSelectedProfile; + + // + //Enter the key enrollment page + //For TTLS and PEAP, only CA cert needs to be cared + // + if (Private->FileType == FileTypeCACert) { + + if (Profile->CACertData != NULL) { + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), Profile->CACertName, NULL); + } else { + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), L"", NULL); + } + } else if (Private->FileType == FileTypeClientCert) { + + if (Profile->ClientCertData != NULL) { + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), Profile->ClientCertName, NULL); + } else { + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), L"", NULL); + } + } + break; + + case KEY_ENROLLED_PRIVATE_KEY_NAME: + + if (Private->CurrentNic->UserSelectedProfile == NULL) { + break; + } + Profile = Private->CurrentNic->UserSelectedProfile; + + if (Profile->PrivateKeyData != NULL) { + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_PRIVATE_KEY_NAME), Profile->PrivateKeyName, NULL); + } else { + HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_PRIVATE_KEY_NAME), L"", NULL); + } + break; + + default: + break; + } + } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) { + switch (QuestionId) { + + case KEY_CONNECT_ACTION: + + if (Private->CurrentNic->UserSelectedProfile == NULL) { + break; + } + Profile = Private->CurrentNic->UserSelectedProfile; + + // + //Restore User Config Data for Page recovery + // + if (IfrNvData->SecurityType == SECURITY_TYPE_WPA2_ENTERPRISE) { + + Profile->EapAuthMethod = IfrNvData->EapAuthMethod; + Profile->EapSecondAuthMethod = IfrNvData->EapSecondAuthMethod; + StrCpyS (Profile->EapIdentity, EAP_IDENTITY_SIZE, IfrNvData->EapIdentity); + } + break; + + default: + break; + } + } else if (Action == EFI_BROWSER_ACTION_CHANGING) { + switch (QuestionId) { + + case KEY_NETWORK_LIST: + + // + //User triggered a scan process. + // + Private->CurrentNic->OneTimeScanRequest = TRUE; + break; + + case KEY_PASSWORD_CONNECT_NETWORK: + case KEY_EAP_PASSWORD_CONNECT_NETWORK: + case KEY_PRIVATE_KEY_PASSWORD: + + if (Private->CurrentNic->UserSelectedProfile == NULL) { + break; + } + Profile = Private->CurrentNic->UserSelectedProfile; + + if (QuestionId == KEY_PASSWORD_CONNECT_NETWORK) { + TempPassword = Profile->Password; + } else if (QuestionId == KEY_EAP_PASSWORD_CONNECT_NETWORK) { + TempPassword = Profile->EapPassword; + } else { + TempPassword = Profile->PrivateKeyPassword; + } + + Status = WifiMgrRecordPassword (Private, Value->string, TempPassword, PASSWORD_STORAGE_SIZE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "[WiFi Connection Manager] Error: Failed to input password!")); + break; + } + + // + // This password is not a new created password, so no need to confirm. + // + Status = EFI_NOT_FOUND; + break; + + case KEY_CONNECT_ACTION: + + ErrorMessage = NULL; + ProfileToConnect = NULL; + + if (Private->CurrentNic->UserSelectedProfile == NULL) { + break; + } + Profile = Private->CurrentNic->UserSelectedProfile; + + if (Private->CurrentNic->ConnectState == WifiMgrDisconnected || + Profile != Private->CurrentNic->CurrentOperateNetwork) { + + // + // When this network is not currently connected, pend it to connect. + // + if (Profile->AKMSuiteSupported && Profile->CipherSuiteSupported) { + + if (Profile->SecurityType == SECURITY_TYPE_NONE || Profile->SecurityType == SECURITY_TYPE_WPA2_PERSONAL) { + + // + // For Open network, connect directly. + // + ProfileToConnect = Profile; + + } else if (Profile->SecurityType == SECURITY_TYPE_WPA2_ENTERPRISE) { + + // + // For WPA/WPA2-Enterprise network, conduct eap configuration first. + // Only EAP-TLS, TTLS and PEAP is supported now! + // + Profile->EapAuthMethod = IfrNvData->EapAuthMethod; + StrCpyS (Profile->EapIdentity, EAP_IDENTITY_SIZE, IfrNvData->EapIdentity); + + if (IfrNvData->EapAuthMethod == EAP_AUTH_METHOD_TTLS || IfrNvData->EapAuthMethod == EAP_AUTH_METHOD_PEAP) { + + Profile->EapSecondAuthMethod = IfrNvData->EapSecondAuthMethod; + ProfileToConnect = Profile; + } else if (IfrNvData->EapAuthMethod == EAP_AUTH_METHOD_TLS) { + ProfileToConnect = Profile; + } else { + ErrorMessage = L"ERROR: Only EAP-TLS, TTLS or PEAP is supported now!"; + } + } else { + ErrorMessage = L"ERROR: Can't connect to this network!"; + } + } else { + ErrorMessage = L"ERROR: This network is not supported!"; + } + + if (ErrorMessage != NULL) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + ErrorMessage, + NULL + ); + } + + if (ProfileToConnect != NULL) { + + Private->CurrentNic->OneTimeConnectRequest = TRUE; + Private->CurrentNic->ConnectPendingNetwork = ProfileToConnect; + } + } else if (Private->CurrentNic->ConnectState == WifiMgrConnectedToAp) { + + // + // This network is currently connected, just disconnect from it. + // + Private->CurrentNic->OneTimeDisconnectRequest = TRUE; + Private->CurrentNic->HasDisconnectPendingNetwork = TRUE; + } + break; + + case KEY_ENROLL_CA_CERT_CONNECT_NETWORK: + + Private->FileType = FileTypeCACert; + break; + + case KEY_ENROLL_CLIENT_CERT_CONNECT_NETWORK: + + Private->FileType = FileTypeClientCert; + break; + + case KEY_EAP_ENROLL_PRIVATE_KEY_FROM_FILE: + + FilePath = NULL; + ChooseFile (NULL, NULL, NULL, &FilePath); + + if (FilePath != NULL) { + + UpdatePrivateKeyFromFile(Private, FilePath); + FreePool (FilePath); + } + break; + + case KEY_EAP_ENROLL_CERT_FROM_FILE: + + // + //User will select a cert file from File Explore + // + FilePath = NULL; + ChooseFile( NULL, NULL, NULL, &FilePath); + + if (FilePath != NULL) { + + UpdateCAFromFile(Private, FilePath); + FreePool (FilePath); + } + break; + + case KEY_SAVE_PRIVATE_KEY_TO_MEM: + + if (Private->FileContext != NULL && Private->FileContext->FHandle != NULL && + Private->CurrentNic->UserSelectedProfile != NULL) { + + // + // Read Private Key file to Buffer + // + Profile = Private->CurrentNic->UserSelectedProfile; + if (Profile->PrivateKeyData != NULL) { + + ZeroMem (Profile->PrivateKeyData, Profile->PrivateKeyDataSize); + FreePool (Profile->PrivateKeyData); + Profile->PrivateKeyData = NULL; + } + + Status = WifiMgrReadFileToBuffer ( + Private->FileContext, + &TempData, + &TempDataSize + ); + if (EFI_ERROR (Status)) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"ERROR: Can't read this private key file!", + NULL + ); + } else { + + ASSERT (Private->FileContext->FileName != NULL); + + Profile->PrivateKeyData = TempData; + Profile->PrivateKeyDataSize = TempDataSize; + StrCpyS(Profile->PrivateKeyName, WIFI_FILENAME_STR_MAX_SIZE, Private->FileContext->FileName); + + DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Private Key: %s has been enrolled! Size: %d\n", + Profile->PrivateKeyName, Profile->PrivateKeyDataSize)); + } + } + break; + + case KEY_SAVE_CERT_TO_MEM: + + if (Private->FileContext != NULL && Private->FileContext->FHandle != NULL && + Private->CurrentNic->UserSelectedProfile != NULL) { + + // + // Read Cert file to Buffer + // + Profile = Private->CurrentNic->UserSelectedProfile; + + if (Private->FileType == FileTypeCACert) { + if (Profile->CACertData != NULL) { + + ZeroMem (Profile->CACertData, Profile->CACertSize); + FreePool (Profile->CACertData); + Profile->CACertData = NULL; + } + } else if (Private->FileType == FileTypeClientCert) { + if (Profile->ClientCertData != NULL) { + + ZeroMem (Profile->ClientCertData, Profile->ClientCertSize); + FreePool (Profile->ClientCertData); + Profile->ClientCertData = NULL; + } + } else { + break; + } + + Status = WifiMgrReadFileToBuffer ( + Private->FileContext, + &TempData, + &TempDataSize + ); + if (EFI_ERROR (Status)) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"ERROR: Can't read this certificate file!", + NULL + ); + } else { + + ASSERT (Private->FileContext->FileName != NULL); + if (Private->FileType == FileTypeCACert) { + + Profile->CACertData = TempData; + Profile->CACertSize = TempDataSize; + StrCpyS(Profile->CACertName, WIFI_FILENAME_STR_MAX_SIZE, Private->FileContext->FileName); + DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] CA Cert: %s has been enrolled! Size: %d\n", + Profile->CACertName, Profile->CACertSize)); + } else { + + Profile->ClientCertData = TempData; + Profile->ClientCertSize = TempDataSize; + StrCpyS(Profile->ClientCertName, WIFI_FILENAME_STR_MAX_SIZE, Private->FileContext->FileName); + DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Client Cert: %s has been enrolled! Size: %d\n", + Profile->ClientCertName, Profile->ClientCertSize)); + } + } + } + break; + + case KEY_ADD_HIDDEN_NETWORK: + + // + // Add a Hidden Network + // + if (StrLen (IfrNvData->SSId) < SSID_MIN_LEN || + Private->HiddenNetworkCount >= HIDDEN_NETWORK_LIST_COUNT_MAX) { + + Status = EFI_ABORTED; + break; + } else { + + // + // Check if this SSId is already in Hidden Network List + // + NET_LIST_FOR_EACH (Entry, &Private->HiddenNetworkList) { + + HiddenNetwork = NET_LIST_USER_STRUCT_S (Entry, WIFI_HIDDEN_NETWORK_DATA, + Link, WIFI_MGR_HIDDEN_NETWORK_SIGNATURE); + if (StrCmp (HiddenNetwork->SSId, IfrNvData->SSId) == 0) { + + Status = EFI_ABORTED; + break; + } + } + } + + HiddenNetwork = (WIFI_HIDDEN_NETWORK_DATA *) AllocateZeroPool (sizeof (WIFI_HIDDEN_NETWORK_DATA)); + if (HiddenNetwork == NULL) { + + Status = EFI_OUT_OF_RESOURCES; + break; + } + HiddenNetwork->Signature = WIFI_MGR_HIDDEN_NETWORK_SIGNATURE; + StrCpyS (HiddenNetwork->SSId, SSID_STORAGE_SIZE, IfrNvData->SSId); + + InsertTailList (&Private->HiddenNetworkList, &HiddenNetwork->Link); + Private->HiddenNetworkCount ++; + + WifiMgrRefreshHiddenList (Private); + break; + + case KEY_REMOVE_HIDDEN_NETWORK: + + // + // Remove Hidden Networks + // + Entry = GetFirstNode (&Private->HiddenNetworkList); + RemoveCount = 0; + for (Index = 0; Index < Private->HiddenNetworkCount; Index ++) { + if (IfrNvData->HiddenNetworkList[Index] != 0) { + + HiddenNetwork = NET_LIST_USER_STRUCT_S (Entry, WIFI_HIDDEN_NETWORK_DATA, Link, WIFI_MGR_HIDDEN_NETWORK_SIGNATURE); + Entry = RemoveEntryList (Entry); + RemoveCount ++; + + FreePool (HiddenNetwork); + } else { + Entry = GetNextNode (&Private->HiddenNetworkList, Entry); + } + } + + Private->HiddenNetworkCount -= RemoveCount; + WifiMgrRefreshHiddenList (Private); + break; + + default: + + if (QuestionId >= KEY_MAC_ENTRY_BASE && QuestionId < KEY_MAC_ENTRY_BASE + Private->NicCount) { + // + // User selects a wireless NIC. + // + Status = WifiMgrSelectNic (Private, QuestionId); + if (EFI_ERROR (Status)) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"ERROR: Fail to operate the wireless NIC!", + NULL + ); + } + } else if (Private->CurrentNic != NULL) { + if (QuestionId >= KEY_AVAILABLE_NETWORK_ENTRY_BASE && + QuestionId <= KEY_AVAILABLE_NETWORK_ENTRY_BASE + Private->CurrentNic->MaxProfileIndex) { + + Status = WifiMgrUserSelectProfileToConnect (Private, QuestionId - KEY_AVAILABLE_NETWORK_ENTRY_BASE); + if (!EFI_ERROR (Status)) { + WifiMgrUpdateConnectMessage(Private->CurrentNic, FALSE, NULL); + } + } + + if (EFI_ERROR (Status)) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"ERROR: Fail to operate this profile!", + NULL + ); + } + } + + break; + } + } else if (Action == EFI_BROWSER_ACTION_CHANGED) { + switch (QuestionId) { + + case KEY_SAVE_CERT_TO_MEM: + case KEY_SAVE_PRIVATE_KEY_TO_MEM: + + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; + break; + + case KEY_NO_SAVE_CERT_TO_MEM: + case KEY_NO_SAVE_PRIVATE_KEY_TO_MEM: + + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; + break; + + default: + + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + break; + } + } else if (Action == EFI_BROWSER_ACTION_RETRIEVE) { + + switch (QuestionId) { + + case KEY_REFRESH_NETWORK_LIST: + + WifiMgrRefreshNetworkList (Private, IfrNvData); + break; + + default: + break; + } + } + + if (!EFI_ERROR (Status)) { + // + // Pass changed uncommitted data back to Form Browser. + // + BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA); + HiiSetBrowserData (&gWifiConfigFormSetGuid, mVendorStorageName, BufferSize, (UINT8 *) IfrNvData, NULL); + } + + ZeroMem (IfrNvData, sizeof (WIFI_MANAGER_IFR_NVDATA)); + FreePool (IfrNvData); + return Status; +} + +/** + Initialize the WiFi configuration form. + + @param[in] Private The pointer to the global private data structure. + + @retval EFI_SUCCESS The configuration form is initialized. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval Other Erros Returned Errors when installing protocols. + +**/ +EFI_STATUS +WifiMgrDxeConfigFormInit ( + WIFI_MGR_PRIVATE_DATA *Private +) +{ + EFI_STATUS Status; + + if (Private == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private->ConfigAccess.ExtractConfig = WifiMgrDxeHiiConfigAccessExtractConfig; + Private->ConfigAccess.RouteConfig = WifiMgrDxeHiiConfigAccessRouteConfig; + Private->ConfigAccess.Callback = WifiMgrDxeHiiConfigAccessCallback; + + // + // Install Device Path Protocol and Config Access protocol to driver handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mWifiMgrDxeHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &Private->ConfigAccess, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Publish our HII data. + // + Private->RegisteredHandle = HiiAddPackages ( + &gWifiConfigFormSetGuid, + Private->DriverHandle, + WifiConnectionManagerDxeStrings, + WifiConnectionManagerDxeBin, + NULL + ); + if (Private->RegisteredHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + Private->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mWifiMgrDxeHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &Private->ConfigAccess, + NULL + ); + return EFI_OUT_OF_RESOURCES; + } + + Private->FileContext = AllocateZeroPool (sizeof (WIFI_MGR_FILE_CONTEXT)); + if (Private->FileContext == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** + Unload the WiFi configuration form. + + @param[in] Private The pointer to the global private data structure. + + @retval EFI_SUCCESS The configuration form is unloaded successfully. + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval Other Errors Returned Erros when uninstalling protocols. + +**/ +EFI_STATUS +WifiMgrDxeConfigFormUnload ( + WIFI_MGR_PRIVATE_DATA *Private +) +{ + EFI_STATUS Status; + + if (Private == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Private->FileContext != NULL) { + + if (Private->FileContext->FHandle != NULL) { + Private->FileContext->FHandle->Close (Private->FileContext->FHandle); + } + + if (Private->FileContext->FileName != NULL) { + FreePool (Private->FileContext->FileName); + } + FreePool (Private->FileContext); + } + + HiiRemovePackages(Private->RegisteredHandle); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Private->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mWifiMgrDxeHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &Private->ConfigAccess, + NULL + ); + + return Status; +} -- cgit v1.2.3