REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the NetworkPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
		
			
				
	
	
		
			1388 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1388 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   The Mac Connection2 Protocol adapter functions for WiFi Connection Manager.
 | |
| 
 | |
|   Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "WifiConnectionMgrDxe.h"
 | |
| 
 | |
| EFI_EAP_TYPE  mEapAuthMethod[] = {
 | |
|   EFI_EAP_TYPE_TTLS,
 | |
|   EFI_EAP_TYPE_PEAP,
 | |
|   EFI_EAP_TYPE_EAPTLS
 | |
| };
 | |
| 
 | |
| EFI_EAP_TYPE  mEapSecondAuthMethod[] = {
 | |
|   EFI_EAP_TYPE_MSCHAPV2
 | |
| };
 | |
| 
 | |
| /**
 | |
|   The callback function for scan operation. This function updates networks
 | |
|   according to the latest scan result, and trigger UI refresh.
 | |
| 
 | |
|   ASSERT when errors occur in config token.
 | |
| 
 | |
|   @param[in]  Event                 The GetNetworks token receive event.
 | |
|   @param[in]  Context               The context of the GetNetworks token.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| WifiMgrOnScanFinished (
 | |
|   IN  EFI_EVENT  Event,
 | |
|   IN  VOID       *Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                     Status;
 | |
|   WIFI_MGR_MAC_CONFIG_TOKEN      *ConfigToken;
 | |
|   WIFI_MGR_DEVICE_DATA           *Nic;
 | |
|   WIFI_MGR_NETWORK_PROFILE       *Profile;
 | |
|   EFI_80211_NETWORK              *Network;
 | |
|   UINTN                          DataSize;
 | |
|   EFI_80211_NETWORK_DESCRIPTION  *NetworkDescription;
 | |
|   EFI_80211_GET_NETWORKS_RESULT  *Result;
 | |
|   LIST_ENTRY                     *Entry;
 | |
|   UINT8                          SecurityType;
 | |
|   BOOLEAN                        AKMSuiteSupported;
 | |
|   BOOLEAN                        CipherSuiteSupported;
 | |
|   CHAR8                          *AsciiSSId;
 | |
|   UINTN                          Index;
 | |
| 
 | |
|   ASSERT (Context != NULL);
 | |
| 
 | |
|   ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN *)Context;
 | |
|   ASSERT (ConfigToken->Nic != NULL);
 | |
|   ASSERT (ConfigToken->Type == TokenTypeGetNetworksToken);
 | |
| 
 | |
|   //
 | |
|   // It is the GetNetworks token, set scan state to "ScanFinished"
 | |
|   //
 | |
|   ConfigToken->Nic->ScanState = WifiMgrScanFinished;
 | |
| 
 | |
|   ASSERT (ConfigToken->Token.GetNetworksToken != NULL);
 | |
|   Result = ConfigToken->Token.GetNetworksToken->Result;
 | |
|   Nic    = ConfigToken->Nic;
 | |
| 
 | |
|   //
 | |
|   // Clean previous result, and update network list according to the scan result
 | |
|   //
 | |
|   Nic->AvailableCount = 0;
 | |
| 
 | |
|   NET_LIST_FOR_EACH (Entry, &Nic->ProfileList) {
 | |
|     Profile = NET_LIST_USER_STRUCT_S (
 | |
|                 Entry,
 | |
|                 WIFI_MGR_NETWORK_PROFILE,
 | |
|                 Link,
 | |
|                 WIFI_MGR_PROFILE_SIGNATURE
 | |
|                 );
 | |
|     Profile->IsAvailable = FALSE;
 | |
|   }
 | |
| 
 | |
|   if (Result == NULL) {
 | |
|     gBS->SignalEvent (Nic->Private->NetworkListRefreshEvent);
 | |
|     WifiMgrFreeToken (ConfigToken);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < Result->NumOfNetworkDesc; Index++) {
 | |
|     NetworkDescription = Result->NetworkDesc + Index;
 | |
|     if (NetworkDescription == NULL) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     Network = &NetworkDescription->Network;
 | |
|     if ((Network == NULL) || (Network->SSId.SSIdLen == 0)) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     Status = WifiMgrCheckRSN (
 | |
|                Network->AKMSuite,
 | |
|                Network->CipherSuite,
 | |
|                Nic,
 | |
|                &SecurityType,
 | |
|                &AKMSuiteSupported,
 | |
|                &CipherSuiteSupported
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       SecurityType         = SECURITY_TYPE_UNKNOWN;
 | |
|       AKMSuiteSupported    = FALSE;
 | |
|       CipherSuiteSupported = FALSE;
 | |
|     }
 | |
| 
 | |
|     AsciiSSId = (CHAR8 *)AllocateZeroPool (sizeof (CHAR8) * (Network->SSId.SSIdLen + 1));
 | |
|     if (AsciiSSId == NULL) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     CopyMem (AsciiSSId, (CHAR8 *)Network->SSId.SSId, sizeof (CHAR8) * Network->SSId.SSIdLen);
 | |
|     *(AsciiSSId + Network->SSId.SSIdLen) = '\0';
 | |
| 
 | |
|     Profile = WifiMgrGetProfileByAsciiSSId (AsciiSSId, SecurityType, &Nic->ProfileList);
 | |
|     if (Profile == NULL) {
 | |
|       if (Nic->MaxProfileIndex >= NETWORK_LIST_COUNT_MAX) {
 | |
|         FreePool (AsciiSSId);
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Create a new profile
 | |
|       //
 | |
|       Profile = AllocateZeroPool (sizeof (WIFI_MGR_NETWORK_PROFILE));
 | |
|       if (Profile == NULL) {
 | |
|         FreePool (AsciiSSId);
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       Profile->Signature    = WIFI_MGR_PROFILE_SIGNATURE;
 | |
|       Profile->NicIndex     = Nic->NicIndex;
 | |
|       Profile->ProfileIndex = Nic->MaxProfileIndex + 1;
 | |
|       AsciiStrToUnicodeStrS (AsciiSSId, Profile->SSId, SSID_STORAGE_SIZE);
 | |
|       InsertTailList (&Nic->ProfileList, &Profile->Link);
 | |
|       Nic->MaxProfileIndex++;
 | |
|     }
 | |
| 
 | |
|     FreePool (AsciiSSId);
 | |
| 
 | |
|     //
 | |
|     // May receive duplicate networks in scan results, check if it has already
 | |
|     // been processed.
 | |
|     //
 | |
|     if (!Profile->IsAvailable) {
 | |
|       Profile->IsAvailable          = TRUE;
 | |
|       Profile->SecurityType         = SecurityType;
 | |
|       Profile->AKMSuiteSupported    = AKMSuiteSupported;
 | |
|       Profile->CipherSuiteSupported = CipherSuiteSupported;
 | |
|       Profile->NetworkQuality       = NetworkDescription->NetworkQuality;
 | |
|       Nic->AvailableCount++;
 | |
| 
 | |
|       //
 | |
|       // Copy BSSType and SSId
 | |
|       //
 | |
|       CopyMem (&Profile->Network, Network, sizeof (EFI_80211_NETWORK));
 | |
| 
 | |
|       //
 | |
|       // Copy AKMSuite list
 | |
|       //
 | |
|       if (Network->AKMSuite != NULL) {
 | |
|         if (Network->AKMSuite->AKMSuiteCount == 0) {
 | |
|           DataSize = sizeof (EFI_80211_AKM_SUITE_SELECTOR);
 | |
|         } else {
 | |
|           DataSize = sizeof (EFI_80211_AKM_SUITE_SELECTOR) + sizeof (EFI_80211_SUITE_SELECTOR)
 | |
|                      * (Network->AKMSuite->AKMSuiteCount - 1);
 | |
|         }
 | |
| 
 | |
|         Profile->Network.AKMSuite = (EFI_80211_AKM_SUITE_SELECTOR *)AllocateZeroPool (DataSize);
 | |
|         if (Profile->Network.AKMSuite == NULL) {
 | |
|           continue;
 | |
|         }
 | |
| 
 | |
|         CopyMem (Profile->Network.AKMSuite, Network->AKMSuite, DataSize);
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Copy CipherSuite list
 | |
|       //
 | |
|       if (Network->CipherSuite != NULL) {
 | |
|         if (Network->CipherSuite->CipherSuiteCount == 0) {
 | |
|           DataSize = sizeof (EFI_80211_CIPHER_SUITE_SELECTOR);
 | |
|         } else {
 | |
|           DataSize = sizeof (EFI_80211_CIPHER_SUITE_SELECTOR) + sizeof (EFI_80211_SUITE_SELECTOR)
 | |
|                      * (Network->CipherSuite->CipherSuiteCount - 1);
 | |
|         }
 | |
| 
 | |
|         Profile->Network.CipherSuite = (EFI_80211_CIPHER_SUITE_SELECTOR *)AllocateZeroPool (DataSize);
 | |
|         if (Profile->Network.CipherSuite == NULL) {
 | |
|           continue;
 | |
|         }
 | |
| 
 | |
|         CopyMem (Profile->Network.CipherSuite, Network->CipherSuite, DataSize);
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // A duplicate network, update signal quality
 | |
|       //
 | |
|       if (Profile->NetworkQuality < NetworkDescription->NetworkQuality) {
 | |
|         Profile->NetworkQuality = NetworkDescription->NetworkQuality;
 | |
|       }
 | |
| 
 | |
|       continue;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   gBS->SignalEvent (Nic->Private->NetworkListRefreshEvent);
 | |
| 
 | |
|   //
 | |
|   // The current connected network should always be available until disconnection
 | |
|   // happens in Wifi FW layer, even when it is not in this time's scan result.
 | |
|   //
 | |
|   if ((Nic->ConnectState == WifiMgrConnectedToAp) && (Nic->CurrentOperateNetwork != NULL)) {
 | |
|     if (!Nic->CurrentOperateNetwork->IsAvailable) {
 | |
|       Nic->CurrentOperateNetwork->IsAvailable = TRUE;
 | |
|       Nic->AvailableCount++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   WifiMgrFreeToken (ConfigToken);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Start scan operation, and send out a token to collect available networks.
 | |
| 
 | |
|   @param[in]  Nic                 Pointer to the device data of the selected NIC.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The operation is completed.
 | |
|   @retval EFI_ALREADY_STARTED     A former scan operation is already ongoing.
 | |
|   @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
 | |
|   @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
 | |
|   @retval Other Errors            Return errors when getting networks from low layer.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WifiMgrStartScan (
 | |
|   IN      WIFI_MGR_DEVICE_DATA  *Nic
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_TPL                       OldTpl;
 | |
|   WIFI_MGR_MAC_CONFIG_TOKEN     *ConfigToken;
 | |
|   EFI_80211_GET_NETWORKS_TOKEN  *GetNetworksToken;
 | |
|   UINT32                        HiddenSSIdIndex;
 | |
|   UINT32                        HiddenSSIdCount;
 | |
|   EFI_80211_SSID                *HiddenSSIdList;
 | |
|   WIFI_HIDDEN_NETWORK_DATA      *HiddenNetwork;
 | |
|   LIST_ENTRY                    *Entry;
 | |
| 
 | |
|   if ((Nic == NULL) || (Nic->Wmp == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (Nic->ScanState == WifiMgrScanning) {
 | |
|     return EFI_ALREADY_STARTED;
 | |
|   }
 | |
| 
 | |
|   Nic->ScanState  = WifiMgrScanning;
 | |
|   OldTpl          = gBS->RaiseTPL (TPL_CALLBACK);
 | |
|   Status          = EFI_SUCCESS;
 | |
|   HiddenSSIdList  = NULL;
 | |
|   HiddenSSIdCount = Nic->Private->HiddenNetworkCount;
 | |
|   HiddenSSIdIndex = 0;
 | |
| 
 | |
|   //
 | |
|   // create a new get network token
 | |
|   //
 | |
|   ConfigToken = AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN));
 | |
|   if (ConfigToken == NULL) {
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   ConfigToken->Type                   = TokenTypeGetNetworksToken;
 | |
|   ConfigToken->Nic                    = Nic;
 | |
|   ConfigToken->Token.GetNetworksToken = AllocateZeroPool (sizeof (EFI_80211_GET_NETWORKS_TOKEN));
 | |
|   if (ConfigToken->Token.GetNetworksToken == NULL) {
 | |
|     WifiMgrFreeToken (ConfigToken);
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   GetNetworksToken = ConfigToken->Token.GetNetworksToken;
 | |
| 
 | |
|   //
 | |
|   // There are some hidden networks to scan, add them into scan list
 | |
|   //
 | |
|   if (HiddenSSIdCount > 0) {
 | |
|     HiddenSSIdList = AllocateZeroPool (HiddenSSIdCount * sizeof (EFI_80211_SSID));
 | |
|     if (HiddenSSIdList == NULL) {
 | |
|       WifiMgrFreeToken (ConfigToken);
 | |
|       gBS->RestoreTPL (OldTpl);
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     HiddenSSIdIndex = 0;
 | |
|     NET_LIST_FOR_EACH (Entry, &Nic->Private->HiddenNetworkList) {
 | |
|       HiddenNetwork = NET_LIST_USER_STRUCT_S (
 | |
|                         Entry,
 | |
|                         WIFI_HIDDEN_NETWORK_DATA,
 | |
|                         Link,
 | |
|                         WIFI_MGR_HIDDEN_NETWORK_SIGNATURE
 | |
|                         );
 | |
|       HiddenSSIdList[HiddenSSIdIndex].SSIdLen = (UINT8)StrLen (HiddenNetwork->SSId);
 | |
|       UnicodeStrToAsciiStrS (
 | |
|         HiddenNetwork->SSId,
 | |
|         (CHAR8 *)HiddenSSIdList[HiddenSSIdIndex].SSId,
 | |
|         SSID_STORAGE_SIZE
 | |
|         );
 | |
|       HiddenSSIdIndex++;
 | |
|     }
 | |
|     GetNetworksToken->Data = AllocateZeroPool (
 | |
|                                sizeof (EFI_80211_GET_NETWORKS_DATA) +
 | |
|                                (HiddenSSIdCount - 1) * sizeof (EFI_80211_SSID)
 | |
|                                );
 | |
|     if (GetNetworksToken->Data == NULL) {
 | |
|       FreePool (HiddenSSIdList);
 | |
|       WifiMgrFreeToken (ConfigToken);
 | |
|       gBS->RestoreTPL (OldTpl);
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     GetNetworksToken->Data->NumOfSSID = HiddenSSIdCount;
 | |
|     CopyMem (GetNetworksToken->Data->SSIDList, HiddenSSIdList, HiddenSSIdCount * sizeof (EFI_80211_SSID));
 | |
|     FreePool (HiddenSSIdList);
 | |
|   } else {
 | |
|     GetNetworksToken->Data = AllocateZeroPool (sizeof (EFI_80211_GET_NETWORKS_DATA));
 | |
|     if (GetNetworksToken->Data == NULL) {
 | |
|       WifiMgrFreeToken (ConfigToken);
 | |
|       gBS->RestoreTPL (OldTpl);
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     GetNetworksToken->Data->NumOfSSID = 0;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Create a handle when scan process ends
 | |
|   //
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_CALLBACK,
 | |
|                   WifiMgrOnScanFinished,
 | |
|                   ConfigToken,
 | |
|                   &GetNetworksToken->Event
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     WifiMgrFreeToken (ConfigToken);
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Start scan ...
 | |
|   //
 | |
|   Status = Nic->Wmp->GetNetworks (Nic->Wmp, GetNetworksToken);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Nic->ScanState = WifiMgrScanFinished;
 | |
|     WifiMgrFreeToken (ConfigToken);
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Configure password to supplicant before connecting to a secured network.
 | |
| 
 | |
|   @param[in]  Nic                 Pointer to the device data of the selected NIC.
 | |
|   @param[in]  Profile             The target network to be connected.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The operation is completed.
 | |
|   @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
 | |
|   @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
 | |
|   @retval EFI_NOT_FOUND           No valid password is found to configure.
 | |
|   @retval Other Errors            Returned errors when setting data to supplicant.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WifiMgrConfigPassword (
 | |
|   IN    WIFI_MGR_DEVICE_DATA      *Nic,
 | |
|   IN    WIFI_MGR_NETWORK_PROFILE  *Profile
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS               Status;
 | |
|   EFI_SUPPLICANT_PROTOCOL  *Supplicant;
 | |
|   EFI_80211_SSID           SSId;
 | |
|   UINT8                    *AsciiPassword;
 | |
| 
 | |
|   if ((Nic == NULL) || (Nic->Supplicant == NULL) || (Profile == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Supplicant = Nic->Supplicant;
 | |
|   //
 | |
|   // Set SSId to supplicant
 | |
|   //
 | |
|   SSId.SSIdLen = Profile->Network.SSId.SSIdLen;
 | |
|   CopyMem (SSId.SSId, Profile->Network.SSId.SSId, sizeof (Profile->Network.SSId.SSId));
 | |
|   Status = Supplicant->SetData (
 | |
|                          Supplicant,
 | |
|                          EfiSupplicant80211TargetSSIDName,
 | |
|                          (VOID *)&SSId,
 | |
|                          sizeof (EFI_80211_SSID)
 | |
|                          );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Set password to supplicant
 | |
|   //
 | |
|   if (StrLen (Profile->Password) < PASSWORD_MIN_LEN) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   AsciiPassword = AllocateZeroPool ((StrLen (Profile->Password) + 1) * sizeof (UINT8));
 | |
|   if (AsciiPassword == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   UnicodeStrToAsciiStrS (Profile->Password, (CHAR8 *)AsciiPassword, PASSWORD_STORAGE_SIZE);
 | |
|   Status = Supplicant->SetData (
 | |
|                          Supplicant,
 | |
|                          EfiSupplicant80211PskPassword,
 | |
|                          AsciiPassword,
 | |
|                          (StrLen (Profile->Password) + 1) * sizeof (UINT8)
 | |
|                          );
 | |
|   ZeroMem (AsciiPassword, AsciiStrLen ((CHAR8 *)AsciiPassword) + 1);
 | |
|   FreePool (AsciiPassword);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Conduct EAP configuration to supplicant before connecting to a EAP network.
 | |
|   Current WiFi Connection Manager only supports three kinds of EAP networks:
 | |
|   1). EAP-TLS (Two-Way Authentication is required in our implementation)
 | |
|   2). EAP-TTLS/MSCHAPv2 (One-Way Authentication is required in our implementation)
 | |
|   3). PEAPv0/MSCHAPv2 (One-Way Authentication is required in our implementation)
 | |
| 
 | |
|   @param[in]  Nic                 Pointer to the device data of the selected NIC.
 | |
|   @param[in]  Profile             The target network to be connected.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The operation is completed.
 | |
|   @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
 | |
|   @retval EFI_UNSUPPORTED         The expected EAP method is not supported.
 | |
|   @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
 | |
|   @retval Other Errors            Returned errors when setting data to supplicant.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WifiMgrConfigEap (
 | |
|   IN    WIFI_MGR_DEVICE_DATA      *Nic,
 | |
|   IN    WIFI_MGR_NETWORK_PROFILE  *Profile
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   EFI_EAP_CONFIGURATION_PROTOCOL  *EapConfig;
 | |
|   EFI_EAP_TYPE                    EapAuthMethod;
 | |
|   EFI_EAP_TYPE                    EapSecondAuthMethod;
 | |
|   EFI_EAP_TYPE                    *AuthMethodList;
 | |
|   CHAR8                           *Identity;
 | |
|   UINTN                           IdentitySize;
 | |
|   CHAR16                          *Password;
 | |
|   UINTN                           PasswordSize;
 | |
|   UINTN                           EncryptPasswordLen;
 | |
|   CHAR8                           *AsciiEncryptPassword;
 | |
|   UINTN                           AuthMethodListSize;
 | |
|   UINTN                           Index;
 | |
| 
 | |
|   if ((Nic == NULL) || (Nic->EapConfig == NULL) || (Profile == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   EapConfig = Nic->EapConfig;
 | |
| 
 | |
|   if (Profile->EapAuthMethod >= EAP_AUTH_METHOD_MAX) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   EapAuthMethod = mEapAuthMethod[Profile->EapAuthMethod];
 | |
| 
 | |
|   if (EapAuthMethod != EFI_EAP_TYPE_EAPTLS) {
 | |
|     if (Profile->EapSecondAuthMethod >= EAP_SEAUTH_METHOD_MAX) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     EapSecondAuthMethod = mEapSecondAuthMethod[Profile->EapSecondAuthMethod];
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // The first time to get Supported Auth Method list, return the size.
 | |
|   //
 | |
|   AuthMethodListSize = 0;
 | |
|   AuthMethodList     = NULL;
 | |
|   Status             = EapConfig->GetData (
 | |
|                                     EapConfig,
 | |
|                                     EFI_EAP_TYPE_ATTRIBUTE,
 | |
|                                     EfiEapConfigEapSupportedAuthMethod,
 | |
|                                     (VOID *)AuthMethodList,
 | |
|                                     &AuthMethodListSize
 | |
|                                     );
 | |
|   if (Status == EFI_SUCCESS) {
 | |
|     //
 | |
|     // No Supported Eap Auth Method
 | |
|     //
 | |
|     return EFI_UNSUPPORTED;
 | |
|   } else if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // The second time to get Supported Auth Method list, return the list.
 | |
|   // In current design, only EAPTLS, TTLS and PEAP are supported
 | |
|   //
 | |
|   AuthMethodList = (EFI_EAP_TYPE *)AllocateZeroPool (AuthMethodListSize);
 | |
|   if (AuthMethodList == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Status = EapConfig->GetData (
 | |
|                         EapConfig,
 | |
|                         EFI_EAP_TYPE_ATTRIBUTE,
 | |
|                         EfiEapConfigEapSupportedAuthMethod,
 | |
|                         (VOID *)AuthMethodList,
 | |
|                         &AuthMethodListSize
 | |
|                         );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     FreePool (AuthMethodList);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check if EapAuthMethod is in supported Auth Method list, if found, skip the loop.
 | |
|   //
 | |
|   for (Index = 0; Index < AuthMethodListSize / sizeof (EFI_EAP_TYPE); Index++) {
 | |
|     if (EapAuthMethod == AuthMethodList[Index]) {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (Index == AuthMethodListSize / sizeof (EFI_EAP_TYPE)) {
 | |
|     FreePool (AuthMethodList);
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   FreePool (AuthMethodList);
 | |
| 
 | |
|   //
 | |
|   // Set Identity to Eap peer, Mandatory field for PEAP and TTLS
 | |
|   //
 | |
|   if (StrLen (Profile->EapIdentity) > 0) {
 | |
|     IdentitySize = sizeof (CHAR8) * (StrLen (Profile->EapIdentity) + 1);
 | |
|     Identity     = AllocateZeroPool (IdentitySize);
 | |
|     if (Identity == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     UnicodeStrToAsciiStrS (Profile->EapIdentity, Identity, IdentitySize);
 | |
|     Status = EapConfig->SetData (
 | |
|                           EapConfig,
 | |
|                           EFI_EAP_TYPE_IDENTITY,
 | |
|                           EfiEapConfigIdentityString,
 | |
|                           (VOID *)Identity,
 | |
|                           IdentitySize - 1
 | |
|                           );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       FreePool (Identity);
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     FreePool (Identity);
 | |
|   } else {
 | |
|     if (EapAuthMethod != EFI_EAP_TYPE_EAPTLS) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Set Auth Method to Eap peer, Mandatory field
 | |
|   //
 | |
|   Status = EapConfig->SetData (
 | |
|                         EapConfig,
 | |
|                         EFI_EAP_TYPE_ATTRIBUTE,
 | |
|                         EfiEapConfigEapAuthMethod,
 | |
|                         (VOID *)&EapAuthMethod,
 | |
|                         sizeof (EapAuthMethod)
 | |
|                         );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if ((EapAuthMethod == EFI_EAP_TYPE_TTLS) || (EapAuthMethod == EFI_EAP_TYPE_PEAP)) {
 | |
|     Status = EapConfig->SetData (
 | |
|                           EapConfig,
 | |
|                           EapAuthMethod,
 | |
|                           EfiEapConfigEap2ndAuthMethod,
 | |
|                           (VOID *)&EapSecondAuthMethod,
 | |
|                           sizeof (EapSecondAuthMethod)
 | |
|                           );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Set Password to Eap peer
 | |
|     //
 | |
|     if (StrLen (Profile->EapPassword) < PASSWORD_MIN_LEN) {
 | |
|       DEBUG ((DEBUG_ERROR, "[WiFi Connection Manager] Error: No Eap Password for Network: %s.\n", Profile->SSId));
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     PasswordSize = sizeof (CHAR16) * (StrLen (Profile->EapPassword) + 1);
 | |
|     Password     = AllocateZeroPool (PasswordSize);
 | |
|     if (Password == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     StrCpyS (Password, PasswordSize, Profile->EapPassword);
 | |
|     Status = EapConfig->SetData (
 | |
|                           EapConfig,
 | |
|                           EFI_EAP_TYPE_MSCHAPV2,
 | |
|                           EfiEapConfigEapMSChapV2Password,
 | |
|                           (VOID *)Password,
 | |
|                           PasswordSize
 | |
|                           );
 | |
|     ZeroMem (Password, PasswordSize);
 | |
|     FreePool (Password);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // If CA cert is required, set it to Eap peer
 | |
|     //
 | |
|     if (Profile->CACertData != NULL) {
 | |
|       Status = EapConfig->SetData (
 | |
|                             EapConfig,
 | |
|                             EapAuthMethod,
 | |
|                             EfiEapConfigEapTlsCACert,
 | |
|                             Profile->CACertData,
 | |
|                             Profile->CACertSize
 | |
|                             );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         return Status;
 | |
|       }
 | |
|     } else {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|   } else if (EapAuthMethod == EFI_EAP_TYPE_EAPTLS) {
 | |
|     //
 | |
|     // Set CA cert to Eap peer
 | |
|     //
 | |
|     if (Profile->CACertData == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     Status = EapConfig->SetData (
 | |
|                           EapConfig,
 | |
|                           EFI_EAP_TYPE_EAPTLS,
 | |
|                           EfiEapConfigEapTlsCACert,
 | |
|                           Profile->CACertData,
 | |
|                           Profile->CACertSize
 | |
|                           );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Set Client cert to Eap peer
 | |
|     //
 | |
|     if (Profile->ClientCertData == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     Status = EapConfig->SetData (
 | |
|                           EapConfig,
 | |
|                           EFI_EAP_TYPE_EAPTLS,
 | |
|                           EfiEapConfigEapTlsClientCert,
 | |
|                           Profile->ClientCertData,
 | |
|                           Profile->ClientCertSize
 | |
|                           );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Set Private key to Eap peer
 | |
|     //
 | |
|     if (Profile->PrivateKeyData == NULL) {
 | |
|       DEBUG ((DEBUG_ERROR, "[WiFi Connection Manager]  Error: No Private Key for Network: %s.\n", Profile->SSId));
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     Status = EapConfig->SetData (
 | |
|                           EapConfig,
 | |
|                           EFI_EAP_TYPE_EAPTLS,
 | |
|                           EfiEapConfigEapTlsClientPrivateKeyFile,
 | |
|                           Profile->PrivateKeyData,
 | |
|                           Profile->PrivateKeyDataSize
 | |
|                           );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     if (StrLen (Profile->PrivateKeyPassword) > 0) {
 | |
|       EncryptPasswordLen   = StrLen (Profile->PrivateKeyPassword);
 | |
|       AsciiEncryptPassword = AllocateZeroPool (EncryptPasswordLen + 1);
 | |
|       if (AsciiEncryptPassword == NULL) {
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       UnicodeStrToAsciiStrS (Profile->PrivateKeyPassword, AsciiEncryptPassword, EncryptPasswordLen + 1);
 | |
|       Status = EapConfig->SetData (
 | |
|                             EapConfig,
 | |
|                             EFI_EAP_TYPE_EAPTLS,
 | |
|                             EfiEapConfigEapTlsClientPrivateKeyFilePassword,
 | |
|                             (VOID *)AsciiEncryptPassword,
 | |
|                             EncryptPasswordLen + 1
 | |
|                             );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         ZeroMem (AsciiEncryptPassword, EncryptPasswordLen + 1);
 | |
|         FreePool (AsciiEncryptPassword);
 | |
|         return Status;
 | |
|       }
 | |
| 
 | |
|       ZeroMem (AsciiEncryptPassword, EncryptPasswordLen + 1);
 | |
|       FreePool (AsciiEncryptPassword);
 | |
|     }
 | |
|   } else {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get current link state from low layer.
 | |
| 
 | |
|   @param[in]   Nic                Pointer to the device data of the selected NIC.
 | |
|   @param[out]  LinkState          The pointer to buffer to retrieve link state.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The operation is completed.
 | |
|   @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
 | |
|   @retval EFI_UNSUPPORTED         Adapter information protocol is not supported.
 | |
|   @retval Other Errors            Returned errors when retrieving link state from low layer.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WifiMgrGetLinkState (
 | |
|   IN   WIFI_MGR_DEVICE_DATA          *Nic,
 | |
|   OUT  EFI_ADAPTER_INFO_MEDIA_STATE  *LinkState
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_TPL                           OldTpl;
 | |
|   UINTN                             DataSize;
 | |
|   EFI_ADAPTER_INFO_MEDIA_STATE      *UndiState;
 | |
|   EFI_ADAPTER_INFORMATION_PROTOCOL  *Aip;
 | |
| 
 | |
|   if ((Nic == NULL) || (LinkState == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Nic->ControllerHandle,
 | |
|                   &gEfiAdapterInformationProtocolGuid,
 | |
|                   (VOID **)&Aip,
 | |
|                   Nic->DriverHandle,
 | |
|                   Nic->ControllerHandle,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   Status = Aip->GetInformation (
 | |
|                   Aip,
 | |
|                   &gEfiAdapterInfoMediaStateGuid,
 | |
|                   (VOID **)&UndiState,
 | |
|                   &DataSize
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   CopyMem (LinkState, UndiState, sizeof (EFI_ADAPTER_INFO_MEDIA_STATE));
 | |
|   FreePool (UndiState);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Prepare configuration work before connecting to the target network.
 | |
|   For WPA2 Personal networks, password should be checked; and for EAP networks, parameters
 | |
|   are different for different networks.
 | |
| 
 | |
|   @param[in]  Nic                 Pointer to the device data of the selected NIC.
 | |
|   @param[in]  Profile             The target network to be connected.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The operation is completed.
 | |
|   @retval EFI_UNSUPPORTED         This network is not supported.
 | |
|   @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WifiMgrPrepareConnection (
 | |
|   IN    WIFI_MGR_DEVICE_DATA      *Nic,
 | |
|   IN    WIFI_MGR_NETWORK_PROFILE  *Profile
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT8       SecurityType;
 | |
|   BOOLEAN     AKMSuiteSupported;
 | |
|   BOOLEAN     CipherSuiteSupported;
 | |
| 
 | |
|   if ((Profile == NULL) || (Nic == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status = WifiMgrCheckRSN (
 | |
|              Profile->Network.AKMSuite,
 | |
|              Profile->Network.CipherSuite,
 | |
|              Nic,
 | |
|              &SecurityType,
 | |
|              &AKMSuiteSupported,
 | |
|              &CipherSuiteSupported
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (AKMSuiteSupported && CipherSuiteSupported) {
 | |
|     switch (SecurityType) {
 | |
|       case SECURITY_TYPE_WPA2_PERSONAL:
 | |
| 
 | |
|         Status = WifiMgrConfigPassword (Nic, Profile);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           if (Status == EFI_NOT_FOUND) {
 | |
|             if (Nic->OneTimeConnectRequest) {
 | |
|               WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Invalid Password!");
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           return Status;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case SECURITY_TYPE_WPA2_ENTERPRISE:
 | |
| 
 | |
|         Status = WifiMgrConfigEap (Nic, Profile);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           if (Status == EFI_INVALID_PARAMETER) {
 | |
|             if (Nic->OneTimeConnectRequest) {
 | |
|               WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Invalid Configuration!");
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           return Status;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case SECURITY_TYPE_NONE:
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         return EFI_UNSUPPORTED;
 | |
|     }
 | |
|   } else {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The callback function for connect operation.
 | |
| 
 | |
|   ASSERT when errors occur in config token.
 | |
| 
 | |
|   @param[in]  Event                 The Connect token receive event.
 | |
|   @param[in]  Context               The context of the connect token.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| WifiMgrOnConnectFinished (
 | |
|   IN  EFI_EVENT  Event,
 | |
|   IN  VOID       *Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                 Status;
 | |
|   WIFI_MGR_MAC_CONFIG_TOKEN  *ConfigToken;
 | |
|   WIFI_MGR_NETWORK_PROFILE   *ConnectedProfile;
 | |
|   UINT8                      SecurityType;
 | |
|   UINT8                      SSIdLen;
 | |
|   CHAR8                      *AsciiSSId;
 | |
| 
 | |
|   ASSERT (Context != NULL);
 | |
| 
 | |
|   ConnectedProfile = NULL;
 | |
|   ConfigToken      = (WIFI_MGR_MAC_CONFIG_TOKEN *)Context;
 | |
|   ASSERT (ConfigToken->Nic != NULL);
 | |
| 
 | |
|   ConfigToken->Nic->ConnectState = WifiMgrDisconnected;
 | |
|   ASSERT (ConfigToken->Type == TokenTypeConnectNetworkToken);
 | |
| 
 | |
|   ASSERT (ConfigToken->Token.ConnectNetworkToken != NULL);
 | |
|   if (ConfigToken->Token.ConnectNetworkToken->Status != EFI_SUCCESS) {
 | |
|     if (ConfigToken->Nic->OneTimeConnectRequest) {
 | |
|       //
 | |
|       // Only update message for user triggered connection
 | |
|       //
 | |
|       if (ConfigToken->Token.ConnectNetworkToken->Status == EFI_ACCESS_DENIED) {
 | |
|         WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed: Permission Denied!");
 | |
|       } else {
 | |
|         WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed!");
 | |
|       }
 | |
| 
 | |
|       ConfigToken->Nic->OneTimeConnectRequest = FALSE;
 | |
|     }
 | |
| 
 | |
|     ConfigToken->Nic->CurrentOperateNetwork = NULL;
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (ConfigToken->Token.ConnectNetworkToken->ResultCode != ConnectSuccess) {
 | |
|     if (ConfigToken->Nic->OneTimeConnectRequest) {
 | |
|       if (ConfigToken->Token.ConnectNetworkToken->ResultCode == ConnectFailedReasonUnspecified) {
 | |
|         WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed: Wrong Password or Unexpected Error!");
 | |
|       } else {
 | |
|         WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed!");
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   if ((ConfigToken->Token.ConnectNetworkToken->Data == NULL) ||
 | |
|       (ConfigToken->Token.ConnectNetworkToken->Data->Network == NULL))
 | |
|   {
 | |
|     //
 | |
|     // An unexpected error occurs, tell low layer to perform a disconnect
 | |
|     //
 | |
|     ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;
 | |
|     WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // A correct connect token received, terminate the connection process
 | |
|   //
 | |
|   Status = WifiMgrCheckRSN (
 | |
|              ConfigToken->Token.ConnectNetworkToken->Data->Network->AKMSuite,
 | |
|              ConfigToken->Token.ConnectNetworkToken->Data->Network->CipherSuite,
 | |
|              ConfigToken->Nic,
 | |
|              &SecurityType,
 | |
|              NULL,
 | |
|              NULL
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     SecurityType = SECURITY_TYPE_UNKNOWN;
 | |
|   }
 | |
| 
 | |
|   SSIdLen   = ConfigToken->Token.ConnectNetworkToken->Data->Network->SSId.SSIdLen;
 | |
|   AsciiSSId = (CHAR8 *)AllocateZeroPool (sizeof (CHAR8) * (SSIdLen + 1));
 | |
|   if (AsciiSSId == NULL) {
 | |
|     ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;
 | |
|     WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   CopyMem (AsciiSSId, ConfigToken->Token.ConnectNetworkToken->Data->Network->SSId.SSId, SSIdLen);
 | |
|   *(AsciiSSId + SSIdLen) = '\0';
 | |
| 
 | |
|   ConnectedProfile = WifiMgrGetProfileByAsciiSSId (AsciiSSId, SecurityType, &ConfigToken->Nic->ProfileList);
 | |
|   FreePool (AsciiSSId);
 | |
|   if (ConnectedProfile == NULL) {
 | |
|     ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;
 | |
|     WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   ConfigToken->Nic->ConnectState = WifiMgrConnectedToAp;
 | |
|   WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);
 | |
| 
 | |
| Exit:
 | |
| 
 | |
|   if (ConfigToken->Nic->ConnectState == WifiMgrDisconnected) {
 | |
|     ConfigToken->Nic->CurrentOperateNetwork = NULL;
 | |
|   }
 | |
| 
 | |
|   ConfigToken->Nic->OneTimeConnectRequest = FALSE;
 | |
|   WifiMgrFreeToken (ConfigToken);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Start connect operation, and send out a token to connect to a target network.
 | |
| 
 | |
|   @param[in]  Nic                 Pointer to the device data of the selected NIC.
 | |
|   @param[in]  Profile             The target network to be connected.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The operation is completed.
 | |
|   @retval EFI_ALREADY_STARTED     Already in "connected" state, need to perform a disconnect
 | |
|                                   operation first.
 | |
|   @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
 | |
|   @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
 | |
|   @retval Other Errors            Return errors when connecting network on low layer.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WifiMgrConnectToNetwork (
 | |
|   IN    WIFI_MGR_DEVICE_DATA      *Nic,
 | |
|   IN    WIFI_MGR_NETWORK_PROFILE  *Profile
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                       Status;
 | |
|   EFI_TPL                          OldTpl;
 | |
|   EFI_ADAPTER_INFO_MEDIA_STATE     LinkState;
 | |
|   WIFI_MGR_MAC_CONFIG_TOKEN        *ConfigToken;
 | |
|   EFI_80211_CONNECT_NETWORK_TOKEN  *ConnectToken;
 | |
| 
 | |
|   if ((Nic == NULL) || (Nic->Wmp == NULL) || (Profile == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status = WifiMgrGetLinkState (Nic, &LinkState);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (LinkState.MediaState == EFI_SUCCESS) {
 | |
|     return EFI_ALREADY_STARTED;
 | |
|   }
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
|   Status = WifiMgrPrepareConnection (Nic, Profile);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Create a new connect token
 | |
|   //
 | |
|   ConfigToken = AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN));
 | |
|   if (ConfigToken == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   ConfigToken->Type                      = TokenTypeConnectNetworkToken;
 | |
|   ConfigToken->Nic                       = Nic;
 | |
|   ConfigToken->Token.ConnectNetworkToken = AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_TOKEN));
 | |
|   if (ConfigToken->Token.ConnectNetworkToken == NULL) {
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   ConnectToken       = ConfigToken->Token.ConnectNetworkToken;
 | |
|   ConnectToken->Data = AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_DATA));
 | |
|   if (ConnectToken->Data == NULL) {
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   ConnectToken->Data->Network = AllocateZeroPool (sizeof (EFI_80211_NETWORK));
 | |
|   if (ConnectToken->Data->Network == NULL) {
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   CopyMem (ConnectToken->Data->Network, &Profile->Network, sizeof (EFI_80211_NETWORK));
 | |
| 
 | |
|   //
 | |
|   // Add event handle and start to connect
 | |
|   //
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_CALLBACK,
 | |
|                   WifiMgrOnConnectFinished,
 | |
|                   ConfigToken,
 | |
|                   &ConnectToken->Event
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   Nic->ConnectState          = WifiMgrConnectingToAp;
 | |
|   Nic->CurrentOperateNetwork = Profile;
 | |
|   WifiMgrUpdateConnectMessage (Nic, FALSE, NULL);
 | |
| 
 | |
|   //
 | |
|   // Start Connecting ...
 | |
|   //
 | |
|   Status = Nic->Wmp->ConnectNetwork (Nic->Wmp, ConnectToken);
 | |
| 
 | |
|   //
 | |
|   // Erase secrets after connection is triggered
 | |
|   //
 | |
|   WifiMgrCleanProfileSecrets (Profile);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     if (Status == EFI_ALREADY_STARTED) {
 | |
|       Nic->ConnectState = WifiMgrConnectedToAp;
 | |
|       WifiMgrUpdateConnectMessage (Nic, TRUE, NULL);
 | |
|     } else {
 | |
|       Nic->ConnectState          = WifiMgrDisconnected;
 | |
|       Nic->CurrentOperateNetwork = NULL;
 | |
| 
 | |
|       if (Nic->OneTimeConnectRequest) {
 | |
|         if (Status == EFI_NOT_FOUND) {
 | |
|           WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Not Available!");
 | |
|         } else {
 | |
|           WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Unexpected Error!");
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
| Exit:
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     WifiMgrFreeToken (ConfigToken);
 | |
|   }
 | |
| 
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] WifiMgrConnectToNetwork: %r\n", Status));
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The callback function for disconnect operation.
 | |
| 
 | |
|   ASSERT when errors occur in config token.
 | |
| 
 | |
|   @param[in]  Event                 The Disconnect token receive event.
 | |
|   @param[in]  Context               The context of the Disconnect token.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| WifiMgrOnDisconnectFinished (
 | |
|   IN EFI_EVENT  Event,
 | |
|   IN VOID       *Context
 | |
|   )
 | |
| {
 | |
|   WIFI_MGR_MAC_CONFIG_TOKEN  *ConfigToken;
 | |
| 
 | |
|   ASSERT (Context != NULL);
 | |
| 
 | |
|   ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN *)Context;
 | |
|   ASSERT (ConfigToken->Nic != NULL);
 | |
|   ASSERT (ConfigToken->Type == TokenTypeDisconnectNetworkToken);
 | |
| 
 | |
|   ASSERT (ConfigToken->Token.DisconnectNetworkToken != NULL);
 | |
|   if (ConfigToken->Token.DisconnectNetworkToken->Status != EFI_SUCCESS) {
 | |
|     ConfigToken->Nic->ConnectState = WifiMgrConnectedToAp;
 | |
|     WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
 | |
|     ConfigToken->Nic->OneTimeDisconnectRequest = FALSE;
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   ConfigToken->Nic->ConnectState          = WifiMgrDisconnected;
 | |
|   ConfigToken->Nic->CurrentOperateNetwork = NULL;
 | |
|   WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);
 | |
|   ConfigToken->Nic->OneTimeDisconnectRequest = FALSE;
 | |
| 
 | |
|   //
 | |
|   // Disconnected network may not be in network list now, trigger a scan again!
 | |
|   //
 | |
|   ConfigToken->Nic->OneTimeScanRequest = TRUE;
 | |
| 
 | |
| Exit:
 | |
|   WifiMgrFreeToken (ConfigToken);
 | |
|   return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Start disconnect operation, and send out a token to disconnect from current connected
 | |
|   network.
 | |
| 
 | |
|   @param[in]  Nic                 Pointer to the device data of the selected NIC.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The operation is completed.
 | |
|   @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
 | |
|   @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
 | |
|   @retval Other Errors            Return errors when disconnecting a network on low layer.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WifiMgrDisconnectToNetwork (
 | |
|   IN    WIFI_MGR_DEVICE_DATA  *Nic
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                          Status;
 | |
|   EFI_TPL                             OldTpl;
 | |
|   WIFI_MGR_MAC_CONFIG_TOKEN           *ConfigToken;
 | |
|   EFI_80211_DISCONNECT_NETWORK_TOKEN  *DisconnectToken;
 | |
| 
 | |
|   if (Nic == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   OldTpl      = gBS->RaiseTPL (TPL_CALLBACK);
 | |
|   Status      = EFI_SUCCESS;
 | |
|   ConfigToken = AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN));
 | |
|   if (ConfigToken == NULL) {
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   ConfigToken->Type                         = TokenTypeDisconnectNetworkToken;
 | |
|   ConfigToken->Nic                          = Nic;
 | |
|   ConfigToken->Token.DisconnectNetworkToken = AllocateZeroPool (sizeof (EFI_80211_DISCONNECT_NETWORK_TOKEN));
 | |
|   if (ConfigToken->Token.DisconnectNetworkToken == NULL) {
 | |
|     WifiMgrFreeToken (ConfigToken);
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   DisconnectToken = ConfigToken->Token.DisconnectNetworkToken;
 | |
| 
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_CALLBACK,
 | |
|                   WifiMgrOnDisconnectFinished,
 | |
|                   ConfigToken,
 | |
|                   &DisconnectToken->Event
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     WifiMgrFreeToken (ConfigToken);
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Nic->ConnectState = WifiMgrDisconnectingToAp;
 | |
|   WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
 | |
| 
 | |
|   Status = Nic->Wmp->DisconnectNetwork (Nic->Wmp, DisconnectToken);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     if (Status == EFI_NOT_FOUND) {
 | |
|       Nic->ConnectState          = WifiMgrDisconnected;
 | |
|       Nic->CurrentOperateNetwork = NULL;
 | |
| 
 | |
|       //
 | |
|       // This network is not in network list now, trigger a scan again!
 | |
|       //
 | |
|       Nic->OneTimeScanRequest = TRUE;
 | |
| 
 | |
|       //
 | |
|       // State has been changed from Connected to Disconnected
 | |
|       //
 | |
|       WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);
 | |
|       Status = EFI_SUCCESS;
 | |
|     } else {
 | |
|       if (Nic->OneTimeDisconnectRequest) {
 | |
|         WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Disconnect Failed: Unexpected Error!");
 | |
|       }
 | |
| 
 | |
|       Nic->ConnectState = WifiMgrConnectedToAp;
 | |
|       WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
 | |
|     }
 | |
| 
 | |
|     WifiMgrFreeToken (ConfigToken);
 | |
|   }
 | |
| 
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The state machine of the connection manager, periodically check the state and
 | |
|   perform a corresponding operation.
 | |
| 
 | |
|   @param[in]  Event                   The timer event to be triggered.
 | |
|   @param[in]  Context                 The context of the Nic device data.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| WifiMgrOnTimerTick (
 | |
|   IN EFI_EVENT  Event,
 | |
|   IN VOID       *Context
 | |
|   )
 | |
| {
 | |
|   WIFI_MGR_DEVICE_DATA          *Nic;
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_ADAPTER_INFO_MEDIA_STATE  LinkState;
 | |
|   WIFI_MGR_NETWORK_PROFILE      *Profile;
 | |
| 
 | |
|   if (Context == NULL) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Nic = (WIFI_MGR_DEVICE_DATA *)Context;
 | |
|   NET_CHECK_SIGNATURE (Nic, WIFI_MGR_DEVICE_DATA_SIGNATURE);
 | |
| 
 | |
|   Status = WifiMgrGetLinkState (Nic, &LinkState);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Error: Failed to get link state!\n"));
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (Nic->LastLinkState.MediaState != LinkState.MediaState) {
 | |
|     if ((Nic->LastLinkState.MediaState == EFI_SUCCESS) && (LinkState.MediaState == EFI_NO_MEDIA)) {
 | |
|       Nic->HasDisconnectPendingNetwork = TRUE;
 | |
|     }
 | |
| 
 | |
|     Nic->LastLinkState.MediaState = LinkState.MediaState;
 | |
|   }
 | |
| 
 | |
|   Nic->ScanTickTime++;
 | |
|   if (((Nic->ScanTickTime > WIFI_SCAN_FREQUENCY) || Nic->OneTimeScanRequest) &&
 | |
|       (Nic->ScanState == WifiMgrScanFinished))
 | |
|   {
 | |
|     Nic->OneTimeScanRequest = FALSE;
 | |
|     Nic->ScanTickTime       = 0;
 | |
| 
 | |
|     DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Scan is triggered.\n"));
 | |
|     WifiMgrStartScan (Nic);
 | |
|   }
 | |
| 
 | |
|   if ((Nic->AvailableCount > 0) && (Nic->ScanState == WifiMgrScanFinished)) {
 | |
|     switch (Nic->ConnectState) {
 | |
|       case WifiMgrDisconnected:
 | |
| 
 | |
|         if (Nic->HasDisconnectPendingNetwork) {
 | |
|           Nic->HasDisconnectPendingNetwork = FALSE;
 | |
|         }
 | |
| 
 | |
|         if (Nic->ConnectPendingNetwork != NULL) {
 | |
|           Profile                    = Nic->ConnectPendingNetwork;
 | |
|           Status                     = WifiMgrConnectToNetwork (Nic, Profile);
 | |
|           Nic->ConnectPendingNetwork = NULL;
 | |
|           if (EFI_ERROR (Status)) {
 | |
|             //
 | |
|             // Some error happened, don't wait for a return connect token!
 | |
|             //
 | |
|             Nic->OneTimeConnectRequest = FALSE;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case WifiMgrConnectingToAp:
 | |
|         break;
 | |
| 
 | |
|       case WifiMgrDisconnectingToAp:
 | |
|         break;
 | |
| 
 | |
|       case WifiMgrConnectedToAp:
 | |
| 
 | |
|         if ((Nic->ConnectPendingNetwork != NULL) || Nic->HasDisconnectPendingNetwork) {
 | |
|           Status = WifiMgrDisconnectToNetwork (Nic);
 | |
|           if (EFI_ERROR (Status)) {
 | |
|             //
 | |
|             // Some error happened, don't wait for a return disconnect token!
 | |
|             //
 | |
|             Nic->OneTimeDisconnectRequest = FALSE;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
| }
 |