2 The Mac Connection2 Protocol adapter functions for WiFi Connection Manager.
4 Copyright (c) 2019 - 2022, 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
:
851 case SECURITY_TYPE_WPA3_PERSONAL
:
853 Status
= WifiMgrConfigPassword (Nic
, Profile
);
854 if (EFI_ERROR (Status
)) {
855 if (Status
== EFI_NOT_FOUND
) {
856 if (Nic
->OneTimeConnectRequest
) {
857 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Invalid Password!");
866 case SECURITY_TYPE_WPA2_ENTERPRISE
:
867 case SECURITY_TYPE_WPA3_ENTERPRISE
:
869 Status
= WifiMgrConfigEap (Nic
, Profile
);
870 if (EFI_ERROR (Status
)) {
871 if (Status
== EFI_INVALID_PARAMETER
) {
872 if (Nic
->OneTimeConnectRequest
) {
873 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Invalid Configuration!");
882 case SECURITY_TYPE_NONE
:
886 return EFI_UNSUPPORTED
;
889 return EFI_UNSUPPORTED
;
896 The callback function for connect operation.
898 ASSERT when errors occur in config token.
900 @param[in] Event The Connect token receive event.
901 @param[in] Context The context of the connect token.
906 WifiMgrOnConnectFinished (
912 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
913 WIFI_MGR_NETWORK_PROFILE
*ConnectedProfile
;
918 ASSERT (Context
!= NULL
);
920 ConnectedProfile
= NULL
;
921 ConfigToken
= (WIFI_MGR_MAC_CONFIG_TOKEN
*)Context
;
922 ASSERT (ConfigToken
->Nic
!= NULL
);
924 ConfigToken
->Nic
->ConnectState
= WifiMgrDisconnected
;
925 ASSERT (ConfigToken
->Type
== TokenTypeConnectNetworkToken
);
927 ASSERT (ConfigToken
->Token
.ConnectNetworkToken
!= NULL
);
928 if (ConfigToken
->Token
.ConnectNetworkToken
->Status
!= EFI_SUCCESS
) {
929 if (ConfigToken
->Nic
->OneTimeConnectRequest
) {
931 // Only update message for user triggered connection
933 if (ConfigToken
->Token
.ConnectNetworkToken
->Status
== EFI_ACCESS_DENIED
) {
934 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed: Permission Denied!");
936 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed!");
939 ConfigToken
->Nic
->OneTimeConnectRequest
= FALSE
;
942 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
946 if (ConfigToken
->Token
.ConnectNetworkToken
->ResultCode
!= ConnectSuccess
) {
947 if (ConfigToken
->Nic
->OneTimeConnectRequest
) {
948 if (ConfigToken
->Token
.ConnectNetworkToken
->ResultCode
== ConnectFailedReasonUnspecified
) {
949 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed: Wrong Password or Unexpected Error!");
951 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Connect Failed!");
958 if ((ConfigToken
->Token
.ConnectNetworkToken
->Data
== NULL
) ||
959 (ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
== NULL
))
962 // An unexpected error occurs, tell low layer to perform a disconnect
964 ConfigToken
->Nic
->HasDisconnectPendingNetwork
= TRUE
;
965 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
970 // A correct connect token received, terminate the connection process
972 Status
= WifiMgrCheckRSN (
973 ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
->AKMSuite
,
974 ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
->CipherSuite
,
980 if (EFI_ERROR (Status
)) {
981 SecurityType
= SECURITY_TYPE_UNKNOWN
;
984 SSIdLen
= ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
->SSId
.SSIdLen
;
985 AsciiSSId
= (CHAR8
*)AllocateZeroPool (sizeof (CHAR8
) * (SSIdLen
+ 1));
986 if (AsciiSSId
== NULL
) {
987 ConfigToken
->Nic
->HasDisconnectPendingNetwork
= TRUE
;
988 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
992 CopyMem (AsciiSSId
, ConfigToken
->Token
.ConnectNetworkToken
->Data
->Network
->SSId
.SSId
, SSIdLen
);
993 *(AsciiSSId
+ SSIdLen
) = '\0';
995 ConnectedProfile
= WifiMgrGetProfileByAsciiSSId (AsciiSSId
, SecurityType
, &ConfigToken
->Nic
->ProfileList
);
996 FreePool (AsciiSSId
);
997 if (ConnectedProfile
== NULL
) {
998 ConfigToken
->Nic
->HasDisconnectPendingNetwork
= TRUE
;
999 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1003 ConfigToken
->Nic
->ConnectState
= WifiMgrConnectedToAp
;
1004 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
1008 if (ConfigToken
->Nic
->ConnectState
== WifiMgrDisconnected
) {
1009 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
1012 ConfigToken
->Nic
->OneTimeConnectRequest
= FALSE
;
1013 WifiMgrFreeToken (ConfigToken
);
1017 Start connect operation, and send out a token to connect to a target network.
1019 @param[in] Nic Pointer to the device data of the selected NIC.
1020 @param[in] Profile The target network to be connected.
1022 @retval EFI_SUCCESS The operation is completed.
1023 @retval EFI_ALREADY_STARTED Already in "connected" state, need to perform a disconnect
1025 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1026 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1027 @retval Other Errors Return errors when connecting network on low layer.
1031 WifiMgrConnectToNetwork (
1032 IN WIFI_MGR_DEVICE_DATA
*Nic
,
1033 IN WIFI_MGR_NETWORK_PROFILE
*Profile
1038 EFI_ADAPTER_INFO_MEDIA_STATE LinkState
;
1039 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
1040 EFI_80211_CONNECT_NETWORK_TOKEN
*ConnectToken
;
1042 if ((Nic
== NULL
) || (Nic
->Wmp
== NULL
) || (Profile
== NULL
)) {
1043 return EFI_INVALID_PARAMETER
;
1046 Status
= WifiMgrGetLinkState (Nic
, &LinkState
);
1047 if (EFI_ERROR (Status
)) {
1051 if (LinkState
.MediaState
== EFI_SUCCESS
) {
1052 return EFI_ALREADY_STARTED
;
1055 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1056 Status
= WifiMgrPrepareConnection (Nic
, Profile
);
1057 if (EFI_ERROR (Status
)) {
1058 gBS
->RestoreTPL (OldTpl
);
1063 // Create a new connect token
1065 ConfigToken
= AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN
));
1066 if (ConfigToken
== NULL
) {
1067 Status
= EFI_OUT_OF_RESOURCES
;
1071 ConfigToken
->Type
= TokenTypeConnectNetworkToken
;
1072 ConfigToken
->Nic
= Nic
;
1073 ConfigToken
->Token
.ConnectNetworkToken
= AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_TOKEN
));
1074 if (ConfigToken
->Token
.ConnectNetworkToken
== NULL
) {
1078 ConnectToken
= ConfigToken
->Token
.ConnectNetworkToken
;
1079 ConnectToken
->Data
= AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_DATA
));
1080 if (ConnectToken
->Data
== NULL
) {
1084 ConnectToken
->Data
->Network
= AllocateZeroPool (sizeof (EFI_80211_NETWORK
));
1085 if (ConnectToken
->Data
->Network
== NULL
) {
1089 CopyMem (ConnectToken
->Data
->Network
, &Profile
->Network
, sizeof (EFI_80211_NETWORK
));
1092 // Add event handle and start to connect
1094 Status
= gBS
->CreateEvent (
1097 WifiMgrOnConnectFinished
,
1099 &ConnectToken
->Event
1101 if (EFI_ERROR (Status
)) {
1105 Nic
->ConnectState
= WifiMgrConnectingToAp
;
1106 Nic
->CurrentOperateNetwork
= Profile
;
1107 WifiMgrUpdateConnectMessage (Nic
, FALSE
, NULL
);
1110 // Start Connecting ...
1112 Status
= Nic
->Wmp
->ConnectNetwork (Nic
->Wmp
, ConnectToken
);
1115 // Erase secrets after connection is triggered
1117 WifiMgrCleanProfileSecrets (Profile
);
1119 if (EFI_ERROR (Status
)) {
1120 if (Status
== EFI_ALREADY_STARTED
) {
1121 Nic
->ConnectState
= WifiMgrConnectedToAp
;
1122 WifiMgrUpdateConnectMessage (Nic
, TRUE
, NULL
);
1124 Nic
->ConnectState
= WifiMgrDisconnected
;
1125 Nic
->CurrentOperateNetwork
= NULL
;
1127 if (Nic
->OneTimeConnectRequest
) {
1128 if (Status
== EFI_NOT_FOUND
) {
1129 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Not Available!");
1131 WifiMgrUpdateConnectMessage (Nic
, FALSE
, L
"Connect Failed: Unexpected Error!");
1141 if (EFI_ERROR (Status
)) {
1142 WifiMgrFreeToken (ConfigToken
);
1145 gBS
->RestoreTPL (OldTpl
);
1147 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] WifiMgrConnectToNetwork: %r\n", Status
));
1152 The callback function for disconnect operation.
1154 ASSERT when errors occur in config token.
1156 @param[in] Event The Disconnect token receive event.
1157 @param[in] Context The context of the Disconnect token.
1162 WifiMgrOnDisconnectFinished (
1167 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
1169 ASSERT (Context
!= NULL
);
1171 ConfigToken
= (WIFI_MGR_MAC_CONFIG_TOKEN
*)Context
;
1172 ASSERT (ConfigToken
->Nic
!= NULL
);
1173 ASSERT (ConfigToken
->Type
== TokenTypeDisconnectNetworkToken
);
1175 ASSERT (ConfigToken
->Token
.DisconnectNetworkToken
!= NULL
);
1176 if (ConfigToken
->Token
.DisconnectNetworkToken
->Status
!= EFI_SUCCESS
) {
1177 ConfigToken
->Nic
->ConnectState
= WifiMgrConnectedToAp
;
1178 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1179 ConfigToken
->Nic
->OneTimeDisconnectRequest
= FALSE
;
1183 ConfigToken
->Nic
->ConnectState
= WifiMgrDisconnected
;
1184 ConfigToken
->Nic
->CurrentOperateNetwork
= NULL
;
1185 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
1186 ConfigToken
->Nic
->OneTimeDisconnectRequest
= FALSE
;
1189 // Disconnected network may not be in network list now, trigger a scan again!
1191 ConfigToken
->Nic
->OneTimeScanRequest
= TRUE
;
1194 WifiMgrFreeToken (ConfigToken
);
1199 Start disconnect operation, and send out a token to disconnect from current connected
1202 @param[in] Nic Pointer to the device data of the selected NIC.
1204 @retval EFI_SUCCESS The operation is completed.
1205 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1206 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1207 @retval Other Errors Return errors when disconnecting a network on low layer.
1211 WifiMgrDisconnectToNetwork (
1212 IN WIFI_MGR_DEVICE_DATA
*Nic
1217 WIFI_MGR_MAC_CONFIG_TOKEN
*ConfigToken
;
1218 EFI_80211_DISCONNECT_NETWORK_TOKEN
*DisconnectToken
;
1221 return EFI_INVALID_PARAMETER
;
1224 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1225 Status
= EFI_SUCCESS
;
1226 ConfigToken
= AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN
));
1227 if (ConfigToken
== NULL
) {
1228 gBS
->RestoreTPL (OldTpl
);
1229 return EFI_OUT_OF_RESOURCES
;
1232 ConfigToken
->Type
= TokenTypeDisconnectNetworkToken
;
1233 ConfigToken
->Nic
= Nic
;
1234 ConfigToken
->Token
.DisconnectNetworkToken
= AllocateZeroPool (sizeof (EFI_80211_DISCONNECT_NETWORK_TOKEN
));
1235 if (ConfigToken
->Token
.DisconnectNetworkToken
== NULL
) {
1236 WifiMgrFreeToken (ConfigToken
);
1237 gBS
->RestoreTPL (OldTpl
);
1238 return EFI_OUT_OF_RESOURCES
;
1241 DisconnectToken
= ConfigToken
->Token
.DisconnectNetworkToken
;
1243 Status
= gBS
->CreateEvent (
1246 WifiMgrOnDisconnectFinished
,
1248 &DisconnectToken
->Event
1250 if (EFI_ERROR (Status
)) {
1251 WifiMgrFreeToken (ConfigToken
);
1252 gBS
->RestoreTPL (OldTpl
);
1256 Nic
->ConnectState
= WifiMgrDisconnectingToAp
;
1257 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1259 Status
= Nic
->Wmp
->DisconnectNetwork (Nic
->Wmp
, DisconnectToken
);
1260 if (EFI_ERROR (Status
)) {
1261 if (Status
== EFI_NOT_FOUND
) {
1262 Nic
->ConnectState
= WifiMgrDisconnected
;
1263 Nic
->CurrentOperateNetwork
= NULL
;
1266 // This network is not in network list now, trigger a scan again!
1268 Nic
->OneTimeScanRequest
= TRUE
;
1271 // State has been changed from Connected to Disconnected
1273 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, TRUE
, NULL
);
1274 Status
= EFI_SUCCESS
;
1276 if (Nic
->OneTimeDisconnectRequest
) {
1277 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, L
"Disconnect Failed: Unexpected Error!");
1280 Nic
->ConnectState
= WifiMgrConnectedToAp
;
1281 WifiMgrUpdateConnectMessage (ConfigToken
->Nic
, FALSE
, NULL
);
1284 WifiMgrFreeToken (ConfigToken
);
1287 gBS
->RestoreTPL (OldTpl
);
1292 The state machine of the connection manager, periodically check the state and
1293 perform a corresponding operation.
1295 @param[in] Event The timer event to be triggered.
1296 @param[in] Context The context of the Nic device data.
1301 WifiMgrOnTimerTick (
1306 WIFI_MGR_DEVICE_DATA
*Nic
;
1308 EFI_ADAPTER_INFO_MEDIA_STATE LinkState
;
1309 WIFI_MGR_NETWORK_PROFILE
*Profile
;
1311 if (Context
== NULL
) {
1315 Nic
= (WIFI_MGR_DEVICE_DATA
*)Context
;
1316 NET_CHECK_SIGNATURE (Nic
, WIFI_MGR_DEVICE_DATA_SIGNATURE
);
1318 Status
= WifiMgrGetLinkState (Nic
, &LinkState
);
1319 if (EFI_ERROR (Status
)) {
1320 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] Error: Failed to get link state!\n"));
1324 if (Nic
->LastLinkState
.MediaState
!= LinkState
.MediaState
) {
1325 if ((Nic
->LastLinkState
.MediaState
== EFI_SUCCESS
) && (LinkState
.MediaState
== EFI_NO_MEDIA
)) {
1326 Nic
->HasDisconnectPendingNetwork
= TRUE
;
1329 Nic
->LastLinkState
.MediaState
= LinkState
.MediaState
;
1332 Nic
->ScanTickTime
++;
1333 if (((Nic
->ScanTickTime
> WIFI_SCAN_FREQUENCY
) || Nic
->OneTimeScanRequest
) &&
1334 (Nic
->ScanState
== WifiMgrScanFinished
))
1336 Nic
->OneTimeScanRequest
= FALSE
;
1337 Nic
->ScanTickTime
= 0;
1339 DEBUG ((DEBUG_INFO
, "[WiFi Connection Manager] Scan is triggered.\n"));
1340 WifiMgrStartScan (Nic
);
1343 if ((Nic
->AvailableCount
> 0) && (Nic
->ScanState
== WifiMgrScanFinished
)) {
1344 switch (Nic
->ConnectState
) {
1345 case WifiMgrDisconnected
:
1347 if (Nic
->HasDisconnectPendingNetwork
) {
1348 Nic
->HasDisconnectPendingNetwork
= FALSE
;
1351 if (Nic
->ConnectPendingNetwork
!= NULL
) {
1352 Profile
= Nic
->ConnectPendingNetwork
;
1353 Status
= WifiMgrConnectToNetwork (Nic
, Profile
);
1354 Nic
->ConnectPendingNetwork
= NULL
;
1355 if (EFI_ERROR (Status
)) {
1357 // Some error happened, don't wait for a return connect token!
1359 Nic
->OneTimeConnectRequest
= FALSE
;
1365 case WifiMgrConnectingToAp
:
1368 case WifiMgrDisconnectingToAp
:
1371 case WifiMgrConnectedToAp
:
1373 if ((Nic
->ConnectPendingNetwork
!= NULL
) || Nic
->HasDisconnectPendingNetwork
) {
1374 Status
= WifiMgrDisconnectToNetwork (Nic
);
1375 if (EFI_ERROR (Status
)) {
1377 // Some error happened, don't wait for a return disconnect token!
1379 Nic
->OneTimeDisconnectRequest
= FALSE
;