2 The Mac Connection2 Protocol adapter functions for WiFi Connection Manager.
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "WifiConnectionMgrDxe.h"
12 EFI_EAP_TYPE mEapAuthMethod
[] = {
18 EFI_EAP_TYPE mEapSecondAuthMethod
[] = {
23 The callback function for scan operation. This function updates networks
24 according to the latest scan result, and trigger UI refresh.
26 ASSERT when errors occur in config token.
28 @param[in] Event The GetNetworks token receive event.
29 @param[in] Context The context of the GetNetworks token.
34 WifiMgrOnScanFinished (
40 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
41 WIFI_MGR_DEVICE_DATA
*Nic
;
42 WIFI_MGR_NETWORK_PROFILE
*Profile
;
43 EFI_80211_NETWORK
*Network
;
45 EFI_80211_NETWORK_DESCRIPTION
*NetworkDescription
;
46 EFI_80211_GET_NETWORKS_RESULT
*Result
;
49 BOOLEAN AKMSuiteSupported
;
50 BOOLEAN CipherSuiteSupported
;
54 ASSERT (Context
!= NULL
);
56 ConfigToken
= (WIFI_MGR_MAC_CONFIG_TOKEN
*)Context
;
57 ASSERT (ConfigToken
->Nic
!= NULL
);
58 ASSERT (ConfigToken
->Type
== TokenTypeGetNetworksToken
);
61 // It is the GetNetworks token, set scan state to "ScanFinished"
63 ConfigToken
->Nic
->ScanState
= WifiMgrScanFinished
;
65 ASSERT (ConfigToken
->Token
.GetNetworksToken
!= NULL
);
66 Result
= ConfigToken
->Token
.GetNetworksToken
->Result
;
67 Nic
= ConfigToken
->Nic
;
70 // Clean previous result, and update network list according to the scan result
72 Nic
->AvailableCount
= 0;
74 NET_LIST_FOR_EACH (Entry
, &Nic
->ProfileList
) {
75 Profile
= NET_LIST_USER_STRUCT_S (
77 WIFI_MGR_NETWORK_PROFILE
,
79 WIFI_MGR_PROFILE_SIGNATURE
81 Profile
->IsAvailable
= FALSE
;
85 gBS
->SignalEvent (Nic
->Private
->NetworkListRefreshEvent
);
86 WifiMgrFreeToken (ConfigToken
);
90 for (Index
= 0; Index
< Result
->NumOfNetworkDesc
; Index
++) {
91 NetworkDescription
= Result
->NetworkDesc
+ Index
;
92 if (NetworkDescription
== NULL
) {
96 Network
= &NetworkDescription
->Network
;
97 if ((Network
== NULL
) || (Network
->SSId
.SSIdLen
== 0)) {
101 Status
= WifiMgrCheckRSN (
103 Network
->CipherSuite
,
107 &CipherSuiteSupported
109 if (EFI_ERROR (Status
)) {
110 SecurityType
= SECURITY_TYPE_UNKNOWN
;
111 AKMSuiteSupported
= FALSE
;
112 CipherSuiteSupported
= FALSE
;
115 AsciiSSId
= (CHAR8
*)AllocateZeroPool (sizeof (CHAR8
) * (Network
->SSId
.SSIdLen
+ 1));
116 if (AsciiSSId
== NULL
) {
120 CopyMem (AsciiSSId
, (CHAR8
*)Network
->SSId
.SSId
, sizeof (CHAR8
) * Network
->SSId
.SSIdLen
);
121 *(AsciiSSId
+ Network
->SSId
.SSIdLen
) = '\0';
123 Profile
= WifiMgrGetProfileByAsciiSSId (AsciiSSId
, SecurityType
, &Nic
->ProfileList
);
124 if (Profile
== NULL
) {
125 if (Nic
->MaxProfileIndex
>= NETWORK_LIST_COUNT_MAX
) {
126 FreePool (AsciiSSId
);
131 // Create a new profile
133 Profile
= AllocateZeroPool (sizeof (WIFI_MGR_NETWORK_PROFILE
));
134 if (Profile
== NULL
) {
135 FreePool (AsciiSSId
);
139 Profile
->Signature
= WIFI_MGR_PROFILE_SIGNATURE
;
140 Profile
->NicIndex
= Nic
->NicIndex
;
141 Profile
->ProfileIndex
= Nic
->MaxProfileIndex
+ 1;
142 AsciiStrToUnicodeStrS (AsciiSSId
, Profile
->SSId
, SSID_STORAGE_SIZE
);
143 InsertTailList (&Nic
->ProfileList
, &Profile
->Link
);
144 Nic
->MaxProfileIndex
++;
147 FreePool (AsciiSSId
);
150 // May receive duplicate networks in scan results, check if it has already
153 if (!Profile
->IsAvailable
) {
154 Profile
->IsAvailable
= TRUE
;
155 Profile
->SecurityType
= SecurityType
;
156 Profile
->AKMSuiteSupported
= AKMSuiteSupported
;
157 Profile
->CipherSuiteSupported
= CipherSuiteSupported
;
158 Profile
->NetworkQuality
= NetworkDescription
->NetworkQuality
;
159 Nic
->AvailableCount
++;
162 // Copy BSSType and SSId
164 CopyMem (&Profile
->Network
, Network
, sizeof (EFI_80211_NETWORK
));
167 // Copy AKMSuite list
169 if (Network
->AKMSuite
!= NULL
) {
170 if (Network
->AKMSuite
->AKMSuiteCount
== 0) {
171 DataSize
= sizeof (EFI_80211_AKM_SUITE_SELECTOR
);
173 DataSize
= sizeof (EFI_80211_AKM_SUITE_SELECTOR
) + sizeof (EFI_80211_SUITE_SELECTOR
)
174 * (Network
->AKMSuite
->AKMSuiteCount
- 1);
177 Profile
->Network
.AKMSuite
= (EFI_80211_AKM_SUITE_SELECTOR
*)AllocateZeroPool (DataSize
);
178 if (Profile
->Network
.AKMSuite
== NULL
) {
182 CopyMem (Profile
->Network
.AKMSuite
, Network
->AKMSuite
, DataSize
);
186 // Copy CipherSuite list
188 if (Network
->CipherSuite
!= NULL
) {
189 if (Network
->CipherSuite
->CipherSuiteCount
== 0) {
190 DataSize
= sizeof (EFI_80211_CIPHER_SUITE_SELECTOR
);
192 DataSize
= sizeof (EFI_80211_CIPHER_SUITE_SELECTOR
) + sizeof (EFI_80211_SUITE_SELECTOR
)
193 * (Network
->CipherSuite
->CipherSuiteCount
- 1);
196 Profile
->Network
.CipherSuite
= (EFI_80211_CIPHER_SUITE_SELECTOR
*)AllocateZeroPool (DataSize
);
197 if (Profile
->Network
.CipherSuite
== NULL
) {
201 CopyMem (Profile
->Network
.CipherSuite
, Network
->CipherSuite
, DataSize
);
205 // A duplicate network, update signal quality
207 if (Profile
->NetworkQuality
< NetworkDescription
->NetworkQuality
) {
208 Profile
->NetworkQuality
= NetworkDescription
->NetworkQuality
;
215 gBS
->SignalEvent (Nic
->Private
->NetworkListRefreshEvent
);
218 // The current connected network should always be available until disconnection
219 // happens in Wifi FW layer, even when it is not in this time's scan result.
221 if ((Nic
->ConnectState
== WifiMgrConnectedToAp
) && (Nic
->CurrentOperateNetwork
!= NULL
)) {
222 if (!Nic
->CurrentOperateNetwork
->IsAvailable
) {
223 Nic
->CurrentOperateNetwork
->IsAvailable
= TRUE
;
224 Nic
->AvailableCount
++;
228 WifiMgrFreeToken (ConfigToken
);
232 Start scan operation, and send out a token to collect available networks.
234 @param[in] Nic Pointer to the device data of the selected NIC.
236 @retval EFI_SUCCESS The operation is completed.
237 @retval EFI_ALREADY_STARTED A former scan operation is already ongoing.
238 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
239 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
240 @retval Other Errors Return errors when getting networks from low layer.
245 IN WIFI_MGR_DEVICE_DATA
*Nic
250 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
251 EFI_80211_GET_NETWORKS_TOKEN
*GetNetworksToken
;
252 UINT32 HiddenSSIdIndex
;
253 UINT32 HiddenSSIdCount
;
254 EFI_80211_SSID
*HiddenSSIdList
;
255 WIFI_HIDDEN_NETWORK_DATA
*HiddenNetwork
;
258 if ((Nic
== NULL
) || (Nic
->Wmp
== NULL
)) {
259 return EFI_INVALID_PARAMETER
;
262 if (Nic
->ScanState
== WifiMgrScanning
) {
263 return EFI_ALREADY_STARTED
;
266 Nic
->ScanState
= WifiMgrScanning
;
267 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
268 Status
= EFI_SUCCESS
;
269 HiddenSSIdList
= NULL
;
270 HiddenSSIdCount
= Nic
->Private
->HiddenNetworkCount
;
274 // create a new get network token
276 ConfigToken
= AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN
));
277 if (ConfigToken
== NULL
) {
278 gBS
->RestoreTPL (OldTpl
);
279 return EFI_OUT_OF_RESOURCES
;
282 ConfigToken
->Type
= TokenTypeGetNetworksToken
;
283 ConfigToken
->Nic
= Nic
;
284 ConfigToken
->Token
.GetNetworksToken
= AllocateZeroPool (sizeof (EFI_80211_GET_NETWORKS_TOKEN
));
285 if (ConfigToken
->Token
.GetNetworksToken
== NULL
) {
286 WifiMgrFreeToken (ConfigToken
);
287 gBS
->RestoreTPL (OldTpl
);
288 return EFI_OUT_OF_RESOURCES
;
291 GetNetworksToken
= ConfigToken
->Token
.GetNetworksToken
;
294 // There are some hidden networks to scan, add them into scan list
296 if (HiddenSSIdCount
> 0) {
297 HiddenSSIdList
= AllocateZeroPool (HiddenSSIdCount
* sizeof (EFI_80211_SSID
));
298 if (HiddenSSIdList
== NULL
) {
299 WifiMgrFreeToken (ConfigToken
);
300 gBS
->RestoreTPL (OldTpl
);
301 return EFI_OUT_OF_RESOURCES
;
305 NET_LIST_FOR_EACH (Entry
, &Nic
->Private
->HiddenNetworkList
) {
306 HiddenNetwork
= NET_LIST_USER_STRUCT_S (
308 WIFI_HIDDEN_NETWORK_DATA
,
310 WIFI_MGR_HIDDEN_NETWORK_SIGNATURE
312 HiddenSSIdList
[HiddenSSIdIndex
].SSIdLen
= (UINT8
)StrLen (HiddenNetwork
->SSId
);
313 UnicodeStrToAsciiStrS (
315 (CHAR8
*)HiddenSSIdList
[HiddenSSIdIndex
].SSId
,
320 GetNetworksToken
->Data
= AllocateZeroPool (
321 sizeof (EFI_80211_GET_NETWORKS_DATA
) +
322 (HiddenSSIdCount
- 1) * sizeof (EFI_80211_SSID
)
324 if (GetNetworksToken
->Data
== NULL
) {
325 FreePool (HiddenSSIdList
);
326 WifiMgrFreeToken (ConfigToken
);
327 gBS
->RestoreTPL (OldTpl
);
328 return EFI_OUT_OF_RESOURCES
;
331 GetNetworksToken
->Data
->NumOfSSID
= HiddenSSIdCount
;
332 CopyMem (GetNetworksToken
->Data
->SSIDList
, HiddenSSIdList
, HiddenSSIdCount
* sizeof (EFI_80211_SSID
));
333 FreePool (HiddenSSIdList
);
335 GetNetworksToken
->Data
= AllocateZeroPool (sizeof (EFI_80211_GET_NETWORKS_DATA
));
336 if (GetNetworksToken
->Data
== NULL
) {
337 WifiMgrFreeToken (ConfigToken
);
338 gBS
->RestoreTPL (OldTpl
);
339 return EFI_OUT_OF_RESOURCES
;
342 GetNetworksToken
->Data
->NumOfSSID
= 0;
346 // Create a handle when scan process ends
348 Status
= gBS
->CreateEvent (
351 WifiMgrOnScanFinished
,
353 &GetNetworksToken
->Event
355 if (EFI_ERROR (Status
)) {
356 WifiMgrFreeToken (ConfigToken
);
357 gBS
->RestoreTPL (OldTpl
);
364 Status
= Nic
->Wmp
->GetNetworks (Nic
->Wmp
, GetNetworksToken
);
365 if (EFI_ERROR (Status
)) {
366 Nic
->ScanState
= WifiMgrScanFinished
;
367 WifiMgrFreeToken (ConfigToken
);
368 gBS
->RestoreTPL (OldTpl
);
372 gBS
->RestoreTPL (OldTpl
);
377 Configure password to supplicant before connecting to a secured network.
379 @param[in] Nic Pointer to the device data of the selected NIC.
380 @param[in] Profile The target network to be connected.
382 @retval EFI_SUCCESS The operation is completed.
383 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
384 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
385 @retval EFI_NOT_FOUND No valid password is found to configure.
386 @retval Other Errors Returned errors when setting data to supplicant.
390 WifiMgrConfigPassword (
391 IN WIFI_MGR_DEVICE_DATA
*Nic
,
392 IN WIFI_MGR_NETWORK_PROFILE
*Profile
396 EFI_SUPPLICANT_PROTOCOL
*Supplicant
;
398 UINT8
*AsciiPassword
;
400 if ((Nic
== NULL
) || (Nic
->Supplicant
== NULL
) || (Profile
== NULL
)) {
401 return EFI_INVALID_PARAMETER
;
404 Supplicant
= Nic
->Supplicant
;
406 // Set SSId to supplicant
408 SSId
.SSIdLen
= Profile
->Network
.SSId
.SSIdLen
;
409 CopyMem (SSId
.SSId
, Profile
->Network
.SSId
.SSId
, sizeof (Profile
->Network
.SSId
.SSId
));
410 Status
= Supplicant
->SetData (
412 EfiSupplicant80211TargetSSIDName
,
414 sizeof (EFI_80211_SSID
)
416 if (EFI_ERROR (Status
)) {
421 // Set password to supplicant
423 if (StrLen (Profile
->Password
) < PASSWORD_MIN_LEN
) {
424 return EFI_NOT_FOUND
;
427 AsciiPassword
= AllocateZeroPool ((StrLen (Profile
->Password
) + 1) * sizeof (UINT8
));
428 if (AsciiPassword
== NULL
) {
429 return EFI_OUT_OF_RESOURCES
;
432 UnicodeStrToAsciiStrS (Profile
->Password
, (CHAR8
*)AsciiPassword
, PASSWORD_STORAGE_SIZE
);
433 Status
= Supplicant
->SetData (
435 EfiSupplicant80211PskPassword
,
437 (StrLen (Profile
->Password
) + 1) * sizeof (UINT8
)
439 ZeroMem (AsciiPassword
, AsciiStrLen ((CHAR8
*)AsciiPassword
) + 1);
440 FreePool (AsciiPassword
);
446 Conduct EAP configuration to supplicant before connecting to a EAP network.
447 Current WiFi Connection Manager only supports three kinds of EAP networks:
448 1). EAP-TLS (Two-Way Authentication is required in our implementation)
449 2). EAP-TTLS/MSCHAPv2 (One-Way Authentication is required in our implementation)
450 3). PEAPv0/MSCHAPv2 (One-Way Authentication is required in our implementation)
452 @param[in] Nic Pointer to the device data of the selected NIC.
453 @param[in] Profile The target network to be connected.
455 @retval EFI_SUCCESS The operation is completed.
456 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
457 @retval EFI_UNSUPPORTED The expected EAP method is not supported.
458 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
459 @retval Other Errors Returned errors when setting data to supplicant.
464 IN WIFI_MGR_DEVICE_DATA
*Nic
,
465 IN WIFI_MGR_NETWORK_PROFILE
*Profile
469 EFI_EAP_CONFIGURATION_PROTOCOL
*EapConfig
;
470 EFI_EAP_TYPE EapAuthMethod
;
471 EFI_EAP_TYPE EapSecondAuthMethod
;
472 EFI_EAP_TYPE
*AuthMethodList
;
477 UINTN EncryptPasswordLen
;
478 CHAR8
*AsciiEncryptPassword
;
479 UINTN AuthMethodListSize
;
482 if ((Nic
== NULL
) || (Nic
->EapConfig
== NULL
) || (Profile
== NULL
)) {
483 return EFI_INVALID_PARAMETER
;
486 EapConfig
= Nic
->EapConfig
;
488 if (Profile
->EapAuthMethod
>= EAP_AUTH_METHOD_MAX
) {
489 return EFI_INVALID_PARAMETER
;
492 EapAuthMethod
= mEapAuthMethod
[Profile
->EapAuthMethod
];
494 if (EapAuthMethod
!= EFI_EAP_TYPE_EAPTLS
) {
495 if (Profile
->EapSecondAuthMethod
>= EAP_SEAUTH_METHOD_MAX
) {
496 return EFI_INVALID_PARAMETER
;
499 EapSecondAuthMethod
= mEapSecondAuthMethod
[Profile
->EapSecondAuthMethod
];
503 // The first time to get Supported Auth Method list, return the size.
505 AuthMethodListSize
= 0;
506 AuthMethodList
= NULL
;
507 Status
= EapConfig
->GetData (
509 EFI_EAP_TYPE_ATTRIBUTE
,
510 EfiEapConfigEapSupportedAuthMethod
,
511 (VOID
*)AuthMethodList
,
514 if (Status
== EFI_SUCCESS
) {
516 // No Supported Eap Auth Method
518 return EFI_UNSUPPORTED
;
519 } else if (Status
!= EFI_BUFFER_TOO_SMALL
) {
524 // The second time to get Supported Auth Method list, return the list.
525 // In current design, only EAPTLS, TTLS and PEAP are supported
527 AuthMethodList
= (EFI_EAP_TYPE
*)AllocateZeroPool (AuthMethodListSize
);
528 if (AuthMethodList
== NULL
) {
529 return EFI_OUT_OF_RESOURCES
;
532 Status
= EapConfig
->GetData (
534 EFI_EAP_TYPE_ATTRIBUTE
,
535 EfiEapConfigEapSupportedAuthMethod
,
536 (VOID
*)AuthMethodList
,
539 if (EFI_ERROR (Status
)) {
540 FreePool (AuthMethodList
);
545 // Check if EapAuthMethod is in supported Auth Method list, if found, skip the loop.
547 for (Index
= 0; Index
< AuthMethodListSize
/ sizeof (EFI_EAP_TYPE
); Index
++) {
548 if (EapAuthMethod
== AuthMethodList
[Index
]) {
553 if (Index
== AuthMethodListSize
/ sizeof (EFI_EAP_TYPE
)) {
554 FreePool (AuthMethodList
);
555 return EFI_UNSUPPORTED
;
558 FreePool (AuthMethodList
);
561 // Set Identity to Eap peer, Mandatory field for PEAP and TTLS
563 if (StrLen (Profile
->EapIdentity
) > 0) {
564 IdentitySize
= sizeof (CHAR8
) * (StrLen (Profile
->EapIdentity
) + 1);
565 Identity
= AllocateZeroPool (IdentitySize
);
566 if (Identity
== NULL
) {
567 return EFI_OUT_OF_RESOURCES
;
570 UnicodeStrToAsciiStrS (Profile
->EapIdentity
, Identity
, IdentitySize
);
571 Status
= EapConfig
->SetData (
573 EFI_EAP_TYPE_IDENTITY
,
574 EfiEapConfigIdentityString
,
578 if (EFI_ERROR (Status
)) {
585 if (EapAuthMethod
!= EFI_EAP_TYPE_EAPTLS
) {
586 return EFI_INVALID_PARAMETER
;
591 // Set Auth Method to Eap peer, Mandatory field
593 Status
= EapConfig
->SetData (
595 EFI_EAP_TYPE_ATTRIBUTE
,
596 EfiEapConfigEapAuthMethod
,
597 (VOID
*)&EapAuthMethod
,
598 sizeof (EapAuthMethod
)
600 if (EFI_ERROR (Status
)) {
604 if ((EapAuthMethod
== EFI_EAP_TYPE_TTLS
) || (EapAuthMethod
== EFI_EAP_TYPE_PEAP
)) {
605 Status
= EapConfig
->SetData (
608 EfiEapConfigEap2ndAuthMethod
,
609 (VOID
*)&EapSecondAuthMethod
,
610 sizeof (EapSecondAuthMethod
)
612 if (EFI_ERROR (Status
)) {
617 // Set Password to Eap peer
619 if (StrLen (Profile
->EapPassword
) < PASSWORD_MIN_LEN
) {
620 DEBUG ((DEBUG_ERROR
, "[WiFi Connection Manager] Error: No Eap Password for Network: %s.\n", Profile
->SSId
));
621 return EFI_INVALID_PARAMETER
;
624 PasswordSize
= sizeof (CHAR16
) * (StrLen (Profile
->EapPassword
) + 1);
625 Password
= AllocateZeroPool (PasswordSize
);
626 if (Password
== NULL
) {
627 return EFI_OUT_OF_RESOURCES
;
630 StrCpyS (Password
, PasswordSize
, Profile
->EapPassword
);
631 Status
= EapConfig
->SetData (
633 EFI_EAP_TYPE_MSCHAPV2
,
634 EfiEapConfigEapMSChapV2Password
,
638 ZeroMem (Password
, PasswordSize
);
640 if (EFI_ERROR (Status
)) {
645 // If CA cert is required, set it to Eap peer
647 if (Profile
->CACertData
!= NULL
) {
648 Status
= EapConfig
->SetData (
651 EfiEapConfigEapTlsCACert
,
655 if (EFI_ERROR (Status
)) {
659 return EFI_INVALID_PARAMETER
;
661 } else if (EapAuthMethod
== EFI_EAP_TYPE_EAPTLS
) {
663 // Set CA cert to Eap peer
665 if (Profile
->CACertData
== NULL
) {
666 return EFI_INVALID_PARAMETER
;
669 Status
= EapConfig
->SetData (
672 EfiEapConfigEapTlsCACert
,
676 if (EFI_ERROR (Status
)) {
681 // Set Client cert to Eap peer
683 if (Profile
->ClientCertData
== NULL
) {
684 return EFI_INVALID_PARAMETER
;
687 Status
= EapConfig
->SetData (
690 EfiEapConfigEapTlsClientCert
,
691 Profile
->ClientCertData
,
692 Profile
->ClientCertSize
694 if (EFI_ERROR (Status
)) {
699 // Set Private key to Eap peer
701 if (Profile
->PrivateKeyData
== NULL
) {
702 DEBUG ((DEBUG_ERROR
, "[WiFi Connection Manager] Error: No Private Key for Network: %s.\n", Profile
->SSId
));
703 return EFI_INVALID_PARAMETER
;
706 Status
= EapConfig
->SetData (
709 EfiEapConfigEapTlsClientPrivateKeyFile
,
710 Profile
->PrivateKeyData
,
711 Profile
->PrivateKeyDataSize
713 if (EFI_ERROR (Status
)) {
717 if (StrLen (Profile
->PrivateKeyPassword
) > 0) {
718 EncryptPasswordLen
= StrLen (Profile
->PrivateKeyPassword
);
719 AsciiEncryptPassword
= AllocateZeroPool (EncryptPasswordLen
+ 1);
720 if (AsciiEncryptPassword
== NULL
) {
721 return EFI_OUT_OF_RESOURCES
;
724 UnicodeStrToAsciiStrS (Profile
->PrivateKeyPassword
, AsciiEncryptPassword
, EncryptPasswordLen
+ 1);
725 Status
= EapConfig
->SetData (
728 EfiEapConfigEapTlsClientPrivateKeyFilePassword
,
729 (VOID
*)AsciiEncryptPassword
,
730 EncryptPasswordLen
+ 1
732 if (EFI_ERROR (Status
)) {
733 ZeroMem (AsciiEncryptPassword
, EncryptPasswordLen
+ 1);
734 FreePool (AsciiEncryptPassword
);
738 ZeroMem (AsciiEncryptPassword
, EncryptPasswordLen
+ 1);
739 FreePool (AsciiEncryptPassword
);
742 return EFI_INVALID_PARAMETER
;
749 Get current link state from low layer.
751 @param[in] Nic Pointer to the device data of the selected NIC.
752 @param[out] LinkState The pointer to buffer to retrieve link state.
754 @retval EFI_SUCCESS The operation is completed.
755 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
756 @retval EFI_UNSUPPORTED Adapter information protocol is not supported.
757 @retval Other Errors Returned errors when retrieving link state from low layer.
761 WifiMgrGetLinkState (
762 IN WIFI_MGR_DEVICE_DATA
*Nic
,
763 OUT EFI_ADAPTER_INFO_MEDIA_STATE
*LinkState
769 EFI_ADAPTER_INFO_MEDIA_STATE
*UndiState
;
770 EFI_ADAPTER_INFORMATION_PROTOCOL
*Aip
;
772 if ((Nic
== NULL
) || (LinkState
== NULL
)) {
773 return EFI_INVALID_PARAMETER
;
776 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
777 Status
= gBS
->OpenProtocol (
778 Nic
->ControllerHandle
,
779 &gEfiAdapterInformationProtocolGuid
,
782 Nic
->ControllerHandle
,
783 EFI_OPEN_PROTOCOL_GET_PROTOCOL
785 if (EFI_ERROR (Status
)) {
786 gBS
->RestoreTPL (OldTpl
);
787 return EFI_UNSUPPORTED
;
790 Status
= Aip
->GetInformation (
792 &gEfiAdapterInfoMediaStateGuid
,
796 if (EFI_ERROR (Status
)) {
797 gBS
->RestoreTPL (OldTpl
);
801 gBS
->RestoreTPL (OldTpl
);
803 CopyMem (LinkState
, UndiState
, sizeof (EFI_ADAPTER_INFO_MEDIA_STATE
));
804 FreePool (UndiState
);
809 Prepare configuration work before connecting to the target network.
810 For WPA2 Personal networks, password should be checked; and for EAP networks, parameters
811 are different for different networks.
813 @param[in] Nic Pointer to the device data of the selected NIC.
814 @param[in] Profile The target network to be connected.
816 @retval EFI_SUCCESS The operation is completed.
817 @retval EFI_UNSUPPORTED This network is not supported.
818 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
822 WifiMgrPrepareConnection (
823 IN WIFI_MGR_DEVICE_DATA
*Nic
,
824 IN WIFI_MGR_NETWORK_PROFILE
*Profile
829 BOOLEAN AKMSuiteSupported
;
830 BOOLEAN CipherSuiteSupported
;
832 if ((Profile
== NULL
) || (Nic
== NULL
)) {
833 return EFI_INVALID_PARAMETER
;
836 Status
= WifiMgrCheckRSN (
837 Profile
->Network
.AKMSuite
,
838 Profile
->Network
.CipherSuite
,
842 &CipherSuiteSupported
844 if (EFI_ERROR (Status
)) {
848 if (AKMSuiteSupported
&& CipherSuiteSupported
) {
849 switch (SecurityType
) {
850 case SECURITY_TYPE_WPA2_PERSONAL
:
852 Status
= WifiMgrConfigPassword (Nic
, Profile
);
853 if (EFI_ERROR (Status
)) {
854 if (Status
== EFI_NOT_FOUND
) {
855 if (Nic
->OneTimeConnectRequest
) {
856 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Invalid Password!");
865 case SECURITY_TYPE_WPA2_ENTERPRISE
:
867 Status
= WifiMgrConfigEap (Nic
, Profile
);
868 if (EFI_ERROR (Status
)) {
869 if (Status
== EFI_INVALID_PARAMETER
) {
870 if (Nic
->OneTimeConnectRequest
) {
871 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Invalid Configuration!");
880 case SECURITY_TYPE_NONE
:
884 return EFI_UNSUPPORTED
;
887 return EFI_UNSUPPORTED
;
894 The callback function for connect operation.
896 ASSERT when errors occur in config token.
898 @param[in] Event The Connect token receive event.
899 @param[in] Context The context of the connect token.
904 WifiMgrOnConnectFinished (
910 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
911 WIFI_MGR_NETWORK_PROFILE
*ConnectedProfile
;
916 ASSERT (Context
!= NULL
);
918 ConnectedProfile
= NULL
;
919 ConfigToken
= (WIFI_MGR_MAC_CONFIG_TOKEN
*)Context
;
920 ASSERT (ConfigToken
->Nic
!= NULL
);
922 ConfigToken
->Nic
->ConnectState
= WifiMgrDisconnected
;
923 ASSERT (ConfigToken
->Type
== TokenTypeConnectNetworkToken
);
925 ASSERT (ConfigToken
->Token
.ConnectNetworkToken
!= NULL
);
926 if (ConfigToken
->Token
.ConnectNetworkToken
->Status
!= EFI_SUCCESS
) {
927 if (ConfigToken
->Nic
->OneTimeConnectRequest
) {
929 // Only update message for user triggered connection
931 if (ConfigToken
->Token
.ConnectNetworkToken
->Status
== EFI_ACCESS_DENIED
) {
932 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed: Permission Denied!");
934 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed!");
937 ConfigToken
->Nic
->OneTimeConnectRequest
= FALSE
;
940 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
944 if (ConfigToken
->Token
.ConnectNetworkToken
->ResultCode
!= ConnectSuccess
) {
945 if (ConfigToken
->Nic
->OneTimeConnectRequest
) {
946 if (ConfigToken
->Token
.ConnectNetworkToken
->ResultCode
== ConnectFailedReasonUnspecified
) {
947 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed: Wrong Password or Unexpected Error!");
949 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed!");
956 if ((ConfigToken
->Token
.ConnectNetworkToken
->Data
== NULL
) ||
957 (ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
== NULL
))
960 // An unexpected error occurs, tell low layer to perform a disconnect
962 ConfigToken
->Nic
->HasDisconnectPendingNetwork
= TRUE
;
963 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
968 // A correct connect token received, terminate the connection process
970 Status
= WifiMgrCheckRSN (
971 ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
->AKMSuite
,
972 ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
->CipherSuite
,
978 if (EFI_ERROR (Status
)) {
979 SecurityType
= SECURITY_TYPE_UNKNOWN
;
982 SSIdLen
= ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
->SSId
.SSIdLen
;
983 AsciiSSId
= (CHAR8
*)AllocateZeroPool (sizeof (CHAR8
) * (SSIdLen
+ 1));
984 if (AsciiSSId
== NULL
) {
985 ConfigToken
->Nic
->HasDisconnectPendingNetwork
= TRUE
;
986 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
990 CopyMem (AsciiSSId
, ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
->SSId
.SSId
, SSIdLen
);
991 *(AsciiSSId
+ SSIdLen
) = '\0';
993 ConnectedProfile
= WifiMgrGetProfileByAsciiSSId (AsciiSSId
, SecurityType
, &ConfigToken
->Nic
->ProfileList
);
994 FreePool (AsciiSSId
);
995 if (ConnectedProfile
== NULL
) {
996 ConfigToken
->Nic
->HasDisconnectPendingNetwork
= TRUE
;
997 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1001 ConfigToken
->Nic
->ConnectState
= WifiMgrConnectedToAp
;
1002 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
1006 if (ConfigToken
->Nic
->ConnectState
== WifiMgrDisconnected
) {
1007 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
1010 ConfigToken
->Nic
->OneTimeConnectRequest
= FALSE
;
1011 WifiMgrFreeToken (ConfigToken
);
1015 Start connect operation, and send out a token to connect to a target network.
1017 @param[in] Nic Pointer to the device data of the selected NIC.
1018 @param[in] Profile The target network to be connected.
1020 @retval EFI_SUCCESS The operation is completed.
1021 @retval EFI_ALREADY_STARTED Already in "connected" state, need to perform a disconnect
1023 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1024 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1025 @retval Other Errors Return errors when connecting network on low layer.
1029 WifiMgrConnectToNetwork (
1030 IN WIFI_MGR_DEVICE_DATA
*Nic
,
1031 IN WIFI_MGR_NETWORK_PROFILE
*Profile
1036 EFI_ADAPTER_INFO_MEDIA_STATE LinkState
;
1037 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
1038 EFI_80211_CONNECT_NETWORK_TOKEN
*ConnectToken
;
1040 if ((Nic
== NULL
) || (Nic
->Wmp
== NULL
) || (Profile
== NULL
)) {
1041 return EFI_INVALID_PARAMETER
;
1044 Status
= WifiMgrGetLinkState (Nic
, &LinkState
);
1045 if (EFI_ERROR (Status
)) {
1049 if (LinkState
.MediaState
== EFI_SUCCESS
) {
1050 return EFI_ALREADY_STARTED
;
1053 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1054 Status
= WifiMgrPrepareConnection (Nic
, Profile
);
1055 if (EFI_ERROR (Status
)) {
1056 gBS
->RestoreTPL (OldTpl
);
1061 // Create a new connect token
1063 ConfigToken
= AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN
));
1064 if (ConfigToken
== NULL
) {
1065 Status
= EFI_OUT_OF_RESOURCES
;
1069 ConfigToken
->Type
= TokenTypeConnectNetworkToken
;
1070 ConfigToken
->Nic
= Nic
;
1071 ConfigToken
->Token
.ConnectNetworkToken
= AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_TOKEN
));
1072 if (ConfigToken
->Token
.ConnectNetworkToken
== NULL
) {
1076 ConnectToken
= ConfigToken
->Token
.ConnectNetworkToken
;
1077 ConnectToken
->Data
= AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_DATA
));
1078 if (ConnectToken
->Data
== NULL
) {
1082 ConnectToken
->Data
->Network
= AllocateZeroPool (sizeof (EFI_80211_NETWORK
));
1083 if (ConnectToken
->Data
->Network
== NULL
) {
1087 CopyMem (ConnectToken
->Data
->Network
, &Profile
->Network
, sizeof (EFI_80211_NETWORK
));
1090 // Add event handle and start to connect
1092 Status
= gBS
->CreateEvent (
1095 WifiMgrOnConnectFinished
,
1097 &ConnectToken
->Event
1099 if (EFI_ERROR (Status
)) {
1103 Nic
->ConnectState
= WifiMgrConnectingToAp
;
1104 Nic
->CurrentOperateNetwork
= Profile
;
1105 WifiMgrUpdateConnectMessage (Nic
, FALSE
, NULL
);
1108 // Start Connecting ...
1110 Status
= Nic
->Wmp
->ConnectNetwork (Nic
->Wmp
, ConnectToken
);
1113 // Erase secrets after connection is triggered
1115 WifiMgrCleanProfileSecrets (Profile
);
1117 if (EFI_ERROR (Status
)) {
1118 if (Status
== EFI_ALREADY_STARTED
) {
1119 Nic
->ConnectState
= WifiMgrConnectedToAp
;
1120 WifiMgrUpdateConnectMessage (Nic
, TRUE
, NULL
);
1122 Nic
->ConnectState
= WifiMgrDisconnected
;
1123 Nic
->CurrentOperateNetwork
= NULL
;
1125 if (Nic
->OneTimeConnectRequest
) {
1126 if (Status
== EFI_NOT_FOUND
) {
1127 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Not Available!");
1129 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Unexpected Error!");
1139 if (EFI_ERROR (Status
)) {
1140 WifiMgrFreeToken (ConfigToken
);
1143 gBS
->RestoreTPL (OldTpl
);
1145 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] WifiMgrConnectToNetwork: %r\n", Status
));
1150 The callback function for disconnect operation.
1152 ASSERT when errors occur in config token.
1154 @param[in] Event The Disconnect token receive event.
1155 @param[in] Context The context of the Disconnect token.
1160 WifiMgrOnDisconnectFinished (
1165 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
1167 ASSERT (Context
!= NULL
);
1169 ConfigToken
= (WIFI_MGR_MAC_CONFIG_TOKEN
*)Context
;
1170 ASSERT (ConfigToken
->Nic
!= NULL
);
1171 ASSERT (ConfigToken
->Type
== TokenTypeDisconnectNetworkToken
);
1173 ASSERT (ConfigToken
->Token
.DisconnectNetworkToken
!= NULL
);
1174 if (ConfigToken
->Token
.DisconnectNetworkToken
->Status
!= EFI_SUCCESS
) {
1175 ConfigToken
->Nic
->ConnectState
= WifiMgrConnectedToAp
;
1176 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1177 ConfigToken
->Nic
->OneTimeDisconnectRequest
= FALSE
;
1181 ConfigToken
->Nic
->ConnectState
= WifiMgrDisconnected
;
1182 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
1183 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
1184 ConfigToken
->Nic
->OneTimeDisconnectRequest
= FALSE
;
1187 // Disconnected network may not be in network list now, trigger a scan again!
1189 ConfigToken
->Nic
->OneTimeScanRequest
= TRUE
;
1192 WifiMgrFreeToken (ConfigToken
);
1197 Start disconnect operation, and send out a token to disconnect from current connected
1200 @param[in] Nic Pointer to the device data of the selected NIC.
1202 @retval EFI_SUCCESS The operation is completed.
1203 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1204 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1205 @retval Other Errors Return errors when disconnecting a network on low layer.
1209 WifiMgrDisconnectToNetwork (
1210 IN WIFI_MGR_DEVICE_DATA
*Nic
1215 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
1216 EFI_80211_DISCONNECT_NETWORK_TOKEN
*DisconnectToken
;
1219 return EFI_INVALID_PARAMETER
;
1222 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1223 Status
= EFI_SUCCESS
;
1224 ConfigToken
= AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN
));
1225 if (ConfigToken
== NULL
) {
1226 gBS
->RestoreTPL (OldTpl
);
1227 return EFI_OUT_OF_RESOURCES
;
1230 ConfigToken
->Type
= TokenTypeDisconnectNetworkToken
;
1231 ConfigToken
->Nic
= Nic
;
1232 ConfigToken
->Token
.DisconnectNetworkToken
= AllocateZeroPool (sizeof (EFI_80211_DISCONNECT_NETWORK_TOKEN
));
1233 if (ConfigToken
->Token
.DisconnectNetworkToken
== NULL
) {
1234 WifiMgrFreeToken (ConfigToken
);
1235 gBS
->RestoreTPL (OldTpl
);
1236 return EFI_OUT_OF_RESOURCES
;
1239 DisconnectToken
= ConfigToken
->Token
.DisconnectNetworkToken
;
1241 Status
= gBS
->CreateEvent (
1244 WifiMgrOnDisconnectFinished
,
1246 &DisconnectToken
->Event
1248 if (EFI_ERROR (Status
)) {
1249 WifiMgrFreeToken (ConfigToken
);
1250 gBS
->RestoreTPL (OldTpl
);
1254 Nic
->ConnectState
= WifiMgrDisconnectingToAp
;
1255 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1257 Status
= Nic
->Wmp
->DisconnectNetwork (Nic
->Wmp
, DisconnectToken
);
1258 if (EFI_ERROR (Status
)) {
1259 if (Status
== EFI_NOT_FOUND
) {
1260 Nic
->ConnectState
= WifiMgrDisconnected
;
1261 Nic
->CurrentOperateNetwork
= NULL
;
1264 // This network is not in network list now, trigger a scan again!
1266 Nic
->OneTimeScanRequest
= TRUE
;
1269 // State has been changed from Connected to Disconnected
1271 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
1272 Status
= EFI_SUCCESS
;
1274 if (Nic
->OneTimeDisconnectRequest
) {
1275 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Disconnect Failed: Unexpected Error!");
1278 Nic
->ConnectState
= WifiMgrConnectedToAp
;
1279 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1282 WifiMgrFreeToken (ConfigToken
);
1285 gBS
->RestoreTPL (OldTpl
);
1290 The state machine of the connection manager, periodically check the state and
1291 perform a corresponding operation.
1293 @param[in] Event The timer event to be triggered.
1294 @param[in] Context The context of the Nic device data.
1299 WifiMgrOnTimerTick (
1304 WIFI_MGR_DEVICE_DATA
*Nic
;
1306 EFI_ADAPTER_INFO_MEDIA_STATE LinkState
;
1307 WIFI_MGR_NETWORK_PROFILE
*Profile
;
1309 if (Context
== NULL
) {
1313 Nic
= (WIFI_MGR_DEVICE_DATA
*)Context
;
1314 NET_CHECK_SIGNATURE (Nic
, WIFI_MGR_DEVICE_DATA_SIGNATURE
);
1316 Status
= WifiMgrGetLinkState (Nic
, &LinkState
);
1317 if (EFI_ERROR (Status
)) {
1318 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] Error: Failed to get link state!\n"));
1322 if (Nic
->LastLinkState
.MediaState
!= LinkState
.MediaState
) {
1323 if ((Nic
->LastLinkState
.MediaState
== EFI_SUCCESS
) && (LinkState
.MediaState
== EFI_NO_MEDIA
)) {
1324 Nic
->HasDisconnectPendingNetwork
= TRUE
;
1327 Nic
->LastLinkState
.MediaState
= LinkState
.MediaState
;
1330 Nic
->ScanTickTime
++;
1331 if (((Nic
->ScanTickTime
> WIFI_SCAN_FREQUENCY
) || Nic
->OneTimeScanRequest
) &&
1332 (Nic
->ScanState
== WifiMgrScanFinished
))
1334 Nic
->OneTimeScanRequest
= FALSE
;
1335 Nic
->ScanTickTime
= 0;
1337 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] Scan is triggered.\n"));
1338 WifiMgrStartScan (Nic
);
1341 if ((Nic
->AvailableCount
> 0) && (Nic
->ScanState
== WifiMgrScanFinished
)) {
1342 switch (Nic
->ConnectState
) {
1343 case WifiMgrDisconnected
:
1345 if (Nic
->HasDisconnectPendingNetwork
) {
1346 Nic
->HasDisconnectPendingNetwork
= FALSE
;
1349 if (Nic
->ConnectPendingNetwork
!= NULL
) {
1350 Profile
= Nic
->ConnectPendingNetwork
;
1351 Status
= WifiMgrConnectToNetwork (Nic
, Profile
);
1352 Nic
->ConnectPendingNetwork
= NULL
;
1353 if (EFI_ERROR (Status
)) {
1355 // Some error happened, don't wait for a return connect token!
1357 Nic
->OneTimeConnectRequest
= FALSE
;
1363 case WifiMgrConnectingToAp
:
1366 case WifiMgrDisconnectingToAp
:
1369 case WifiMgrConnectedToAp
:
1371 if ((Nic
->ConnectPendingNetwork
!= NULL
) || Nic
->HasDisconnectPendingNetwork
) {
1372 Status
= WifiMgrDisconnectToNetwork (Nic
);
1373 if (EFI_ERROR (Status
)) {
1375 // Some error happened, don't wait for a return disconnect token!
1377 Nic
->OneTimeDisconnectRequest
= FALSE
;